home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / screen3 / part07 < prev    next >
Encoding:
Text File  |  1991-12-19  |  71.2 KB  |  3,545 lines

  1. Newsgroups: comp.sources.unix
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject: v25i047: Screen3 - multiple windows on an ASCII terminal, Part07/08
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  8. Posting-Number: Volume 25, Issue 47
  9. Archive-Name: screen3/part07
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 7 (of 8)."
  18. # Contents:  ansi.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu Dec 19 17:36:06 1991
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'ansi.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'ansi.c'\"
  23. else
  24. echo shar: Extracting \"'ansi.c'\" \(68134 characters\)
  25. sed "s/^X//" >'ansi.c' <<'END_OF_FILE'
  26. X/* Copyright (c) 1991
  27. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  28. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  29. X * Copyright (c) 1987 Oliver Laumann
  30. X * All rights reserved.  Not derived from licensed software.
  31. X *
  32. X * Permission is granted to freely use, copy, modify, and redistribute
  33. X * this software, provided that no attempt is made to gain profit from it,
  34. X * the authors are not construed to be liable for any results of using the
  35. X * software, alterations are clearly marked as such, and this notice is
  36. X * not modified.
  37. X *
  38. X * Noteworthy contributors to screen's design and implementation:
  39. X *    Wayne Davison (davison@borland.com)
  40. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  41. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  42. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  43. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  44. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  45. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  46. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  47. X *    Marc Boucher (marc@CAM.ORG)
  48. X *
  49. X ****************************************************************
  50. X */
  51. X
  52. X#ifndef lint
  53. X  static char rcs_id[] = "$Id: ansi.c,v 1.88 91/10/11 11:27:40 jnweiger Exp $ FAU";
  54. X#endif
  55. X
  56. X#include <stdio.h>
  57. X#if defined(BSD) || defined(sequent) || defined(pyr)
  58. X# include <strings.h>
  59. X#else
  60. X# include <string.h>
  61. X#endif
  62. X#include <sys/types.h>
  63. X#include "config.h"
  64. X#include "screen.h"
  65. X#include "ansi.h"
  66. X#include "extern.h"
  67. X#include <fcntl.h>
  68. X#ifndef sun /* we want to know about TIOCGWINSZ. jw. */
  69. X# include <sys/ioctl.h>
  70. X#endif
  71. X
  72. extern char *getenv(), *tgetstr(), *tgoto();
  73. X#ifndef __STDC__
  74. extern char *malloc();
  75. X#endif
  76. X
  77. extern struct win *fore;
  78. extern int ForeNum;
  79. extern force_vt, assume_LP;
  80. extern int BellDisplayed;
  81. extern int MsgMinWait;
  82. X
  83. X#ifdef TIOCGWINSZ
  84. extern struct winsize glwz;
  85. X#endif
  86. X
  87. static int rows, cols;        /* window size of the curr window. */
  88. int TermcapROWS, TermcapCOLS;    /* defaults that we learned from termcap */
  89. int maxwidth, Z0width, Z1width;
  90. int default_width, default_height;    /* width/height a new window will get */
  91. X
  92. int screenwidth, screenheight;    /* width/height of the fore window */
  93. int screentop, screenbot;    /* scrollregion start/end */
  94. int screenx, screeny;        /* cursor position */
  95. char GlobalAttr, GlobalCharset;
  96. int insert;            /* insert mode */
  97. int keypad;
  98. int flow;
  99. X
  100. int status;
  101. static int status_lastx, status_lasty;
  102. X
  103. int flowctl, wrap = 1, default_monitor = 0; 
  104. int visual_bell = 0, termcapHS, use_hardstatus = 1;
  105. char *Termcap, *extra_incap, *extra_outcap;
  106. static int Termcaplen;
  107. char *blank, *null, *LastMsg;
  108. char Term[MAXSTR+5];    /* +5: "TERM=" */
  109. char screenterm[20] = "screen";
  110. char *Z0, *Z1;
  111. int ISO2022, HS;
  112. time_t TimeDisplayed, time();
  113. X
  114. X/*
  115. X * the termcap routines need this to work
  116. X */
  117. short ospeed;
  118. char *BC;
  119. char *UP;
  120. X
  121. static void AddCap __P((char *));
  122. static void MakeString __P((char *, char *, int, char *));
  123. static int Special __P((int));
  124. static void DoESC __P((int, int ));
  125. static void DoCSI __P((int, int ));
  126. static void CPutStr __P((char *, int));
  127. static void SetChar __P(());
  128. static void StartString __P((enum string_t));
  129. static void AddChar __P((int ));
  130. static void PrintChar __P((int ));
  131. static void PrintFlush __P((void));
  132. static void KeypadMode __P((int));
  133. static void FlowMode __P((int));
  134. static void DesignateCharset __P((int, int ));
  135. static void MapCharset __P((int));
  136. static void SaveCursor __P((void));
  137. static void RestoreCursor __P((void));
  138. static void CountChars __P((int));
  139. static int CalcCost __P((char *));
  140. static int Rewrite __P((int, int, int, int));
  141. static void BackSpace __P((void));
  142. static void Return __P((void));
  143. static void LineFeed __P((int));
  144. static void ReverseLineFeed __P((void));
  145. static void InsertAChar __P((int));
  146. static void InsertChar __P((int));
  147. static void DeleteChar __P((int));
  148. static void DeleteLine __P((int));
  149. static void InsertLine __P((int));
  150. static void ScrollUpMap __P((int));
  151. static void ScrollDownMap __P((int));
  152. static void Scroll __P((char *, int, int, char *));
  153. static void ForwardTab __P((void));
  154. static void BackwardTab __P((void));
  155. static void ClearScreen __P((void));
  156. static void ClearFromBOS __P((void));
  157. static void ClearToEOS __P((void));
  158. static void ClearLine __P((void));
  159. static void ClearToEOL __P((void));
  160. static void ClearFromBOL __P((void));
  161. static void ClearInLine __P((int, int, int, int ));
  162. static void CursorRight __P(());
  163. static void CursorUp __P(());
  164. static void CursorDown __P(());
  165. static void CursorLeft __P(());
  166. static void ASetMode __P((int));
  167. static void SelectRendition __P((void));
  168. static void FillWithEs __P((void));
  169. static void RedisplayLine __P((char *, char *, char *, int, int, int ));
  170. static void FindAKA __P((void));
  171. static void SetCurr __P((struct win *));
  172. static void inpRedisplayLine __P((int, int, int, int));
  173. static void process_inp_input __P((char **, int *));
  174. static void AbortInp __P((void));
  175. static void AKAfin __P((char *, int));
  176. static void Colonfin __P((char *, int));
  177. static void RAW_PUTCHAR __P((int));
  178. static char *e_tgetstr __P((char *, char **));
  179. static int e_tgetflag __P((char *));
  180. static int e_tgetnum __P((char *));
  181. X
  182. X
  183. static char *tbuf, *tentry, *termname;
  184. static char *tp;
  185. static char *TI, *TE, *BL, *VB, *CR, *NL, *CL, *IS;
  186. char *WS;    /* used in ResizeScreen() */
  187. char *CE;    /* used in help.c */
  188. static char *CM, *US, *UE, *SO, *SE, *CD, *DO, *SR, *SF, *AL;
  189. static char *CS, *DL, *DC, *IC, *IM, *EI, *ND, *KS, *KE;
  190. static char *MB, *MD, *MH, *MR, *ME, *PO, *PF, *HO;
  191. static char *TS, *FS, *DS, *VI, *VE, *VS;
  192. static char *CDC, *CDL, *CAL, *CUP, *CDO, *CLE, *CRI, *CIC;
  193. static char *attrtab[NATTR];
  194. static AM, MS, COP;
  195. int LP;
  196. X/*
  197. X * Do not confuse S0 (es-zero), E0 (e-zero) with SO (es-oh), PO (pe-oh),
  198. X * Z0 (z-zero), DO (de-oh)... :-)
  199. X */
  200. static char *C0, *S0, *E0;
  201. static char c0_tab[256];
  202. X/*
  203. X */
  204. static screencap = 0;
  205. char *OldImage, *OldAttr, *OldFont;
  206. static struct win *curr;
  207. static display = 1;
  208. static StrCost;
  209. static UPcost, DOcost, LEcost, NDcost, CRcost, IMcost, EIcost, NLcost;
  210. static tcLineLen;
  211. static StatLen;
  212. static lp_missing = 0;
  213. X
  214. int in_ovl;
  215. int ovl_blockfore;
  216. void (*ovl_process)();
  217. void (*ovl_RedisplayLine)();
  218. int (*ovl_Rewrite)();
  219. X
  220. static char *KeyCaps[] =
  221. X{
  222. X  "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9",
  223. X  "kb", "kd", "kh", "kl", "ko", "kr", "ku",
  224. X  "K1", "K2", "K3", "K4", "K5",
  225. X  "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "l8", "l9"
  226. X};
  227. X#define NKEYCAPS (sizeof(KeyCaps)/sizeof(*KeyCaps))
  228. static char *KeyCapsArr[NKEYCAPS];
  229. X
  230. static char TermcapConst[] = "\\\n\
  231. X\t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
  232. X\t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
  233. X\t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\
  234. X\t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:xv:";
  235. X
  236. void
  237. InitTermcap()
  238. X{
  239. X  register char *s;
  240. X  int i;
  241. X
  242. X  screencap = 0;
  243. X  if ((s = getenv("SCREENCAP")) != 0)
  244. X    {
  245. X      if ((Termcap = malloc((unsigned) strlen(s) + 10)) != 0)
  246. X    {
  247. X      sprintf(Termcap, "TERMCAP=%s", s);
  248. X      screencap = 1;
  249. X    }
  250. X    }
  251. X  else
  252. X    Termcap = malloc((unsigned) 1024);
  253. X  Termcaplen = 0;
  254. X  tbuf = malloc((unsigned) 1024);
  255. X  tentry = tp = malloc((unsigned) 1024);
  256. X  if (!(Termcap && tbuf && tentry))
  257. X    Msg_nomem;
  258. X  bzero(tbuf, 1024);
  259. X  if ((termname = getenv("TERM")) == 0)
  260. X    Msg(0, "No TERM in environment.");
  261. X  debug1("InitTermcap: looking for tgetent('%s');\n", termname);
  262. X  if (tgetent(tbuf, termname) != 1)
  263. X    Msg(0, "Cannot find termcap entry for %s.", termname);
  264. X  debug1("got it:\n%s\n",tbuf);
  265. X#ifdef DEBUG
  266. X  if (extra_incap)
  267. X    debug1("Extra incap: %s\n", extra_incap);
  268. X  if (extra_outcap)
  269. X    debug1("Extra outcap: %s\n", extra_outcap);
  270. X#endif
  271. X
  272. X  TermcapCOLS = TermcapROWS = 0;
  273. X  if (s = getenv("COLUMNS"))
  274. X    TermcapCOLS = atoi(s);
  275. X  if (TermcapCOLS <= 0)
  276. X    TermcapCOLS = e_tgetnum("co");
  277. X  if (TermcapCOLS <= 0)
  278. X    TermcapCOLS = 80;
  279. X  if (s = getenv("LINES"))
  280. X    TermcapROWS = atoi(s);
  281. X  if (TermcapROWS <= 0)
  282. X    TermcapROWS = e_tgetnum("li");
  283. X  if (TermcapROWS <= 0)
  284. X    TermcapROWS = 24;
  285. X
  286. X  if (e_tgetflag("hc"))
  287. X    Msg(0, "You can't run screen on a hardcopy terminal.");
  288. X  if (e_tgetflag("os"))
  289. X    Msg(0, "You can't run screen on a terminal that overstrikes.");
  290. X  if (e_tgetflag("ns"))
  291. X    Msg(0, "Terminal must support scrolling.");
  292. X  if (!(CL = e_tgetstr("cl", &tp)))
  293. X    Msg(0, "Clear screen capability required.");
  294. X  if (!(CM = e_tgetstr("cm", &tp)))
  295. X    Msg(0, "Addressable cursor capability required.");
  296. X  switch (flowctl)
  297. X    {
  298. X    case 0:
  299. X      flow = !e_tgetflag("NF");
  300. X      flowctl = flow + 1;
  301. X      break;
  302. X    case 1:
  303. X      flow = 0;
  304. X      break;
  305. X    case 2:
  306. X    case 3:
  307. X      flow = 1;
  308. X      break;
  309. X    }
  310. X  AM = e_tgetflag("am");
  311. X  LP = assume_LP || (!extra_incap && !strncmp(termname, "vt", 2))
  312. X           || !AM || e_tgetflag("LP") || e_tgetflag("xv");
  313. X  COP = e_tgetflag("OP");
  314. X  HO = e_tgetstr("ho", &tp);
  315. X  TI = e_tgetstr("ti", &tp);
  316. X  TE = e_tgetstr("te", &tp);
  317. X  if (!(BL = e_tgetstr("bl", &tp)))
  318. X    BL = "\007";
  319. X  VB = e_tgetstr("vb", &tp);
  320. X  if (!(BC = e_tgetstr("bc", &tp)))
  321. X    {
  322. X      if (e_tgetflag("bs"))
  323. X    BC = "\b";
  324. X      else
  325. X    BC = e_tgetstr("le", &tp);
  326. X    }
  327. X  if (!(CR = e_tgetstr("cr", &tp)))
  328. X    CR = "\r";
  329. X  if (!(NL = e_tgetstr("nl", &tp)))
  330. X    NL = "\n";
  331. X  IS = e_tgetstr("is", &tp);
  332. X  MS = 1;
  333. X  if (e_tgetnum("sg") <= 0 && e_tgetnum("ug") <= 0)
  334. X    {
  335. X      MS = e_tgetflag("ms");
  336. X      attrtab[ATTR_DI] = MH = e_tgetstr("mh", &tp);    /* Dim */
  337. X      attrtab[ATTR_US] = US = e_tgetstr("us", &tp);    /* Underline */
  338. X      attrtab[ATTR_BD] = MD = e_tgetstr("md", &tp);    /* Bold */
  339. X      attrtab[ATTR_RV] = MR = e_tgetstr("mr", &tp);    /* Reverse */
  340. X      attrtab[ATTR_SO] = SO = e_tgetstr("so", &tp);    /* Standout */
  341. X      attrtab[ATTR_BL] = MB = e_tgetstr("mb", &tp);    /* Blinking */
  342. X      ME = e_tgetstr("me", &tp);
  343. X      SE = e_tgetstr("se", &tp);
  344. X      UE = e_tgetstr("ue", &tp);
  345. X      /*
  346. X       * Does ME also reverse the effect of SO and/or US?  This is not
  347. X       * clearly specified by the termcap manual. Anyway, we should at
  348. X       * least look whether ME and SE/UE are equal:
  349. X       */
  350. X      if (UE && ((SE && strcmp(SE, UE) == 0) || (ME && strcmp(ME, UE) == 0)))
  351. X    UE = 0;
  352. X      if (SE && (ME && strcmp(ME, SE) == 0))
  353. X    SE = 0;
  354. X
  355. X      /* Set up missing entries */
  356. X      s = 0;
  357. X      for (i = NATTR-1; i >= 0; i--)
  358. X    if (attrtab[i])
  359. X      s = attrtab[i];
  360. X      for (i = 0; i < NATTR; i++)
  361. X    {
  362. X      if (attrtab[i] == 0)
  363. X        attrtab[i] = s;
  364. X      else
  365. X        s = attrtab[i];
  366. X    }
  367. X    }
  368. X  else
  369. X    {
  370. X      US = UE = SO = SE = MB = MD = MH = MR = ME = 0;
  371. X      for (i = 0; i < NATTR; i++)
  372. X    attrtab[i] = 0;
  373. X    }
  374. X  CE = e_tgetstr("ce", &tp);
  375. X  CD = e_tgetstr("cd", &tp);
  376. X  if (!(DO = e_tgetstr("do", &tp)))
  377. X    DO = NL;
  378. X  UP = e_tgetstr("up", &tp);
  379. X  ND = e_tgetstr("nd", &tp);
  380. X  SR = e_tgetstr("sr", &tp);
  381. X  if (!(SF = e_tgetstr("sf", &tp)))
  382. X    SF = NL;
  383. X  AL = e_tgetstr("al", &tp);
  384. X  DL = e_tgetstr("dl", &tp);
  385. X  CS = e_tgetstr("cs", &tp);
  386. X  DC = e_tgetstr("dc", &tp);
  387. X  IC = e_tgetstr("ic", &tp);
  388. X  CIC = e_tgetstr("IC", &tp);
  389. X  CDC = e_tgetstr("DC", &tp);
  390. X  CDL = e_tgetstr("DL", &tp);
  391. X  CAL = e_tgetstr("AL", &tp);
  392. X  CUP = e_tgetstr("UP", &tp);
  393. X  CDO = e_tgetstr("DO", &tp);
  394. X  CLE = e_tgetstr("LE", &tp);
  395. X  CRI = e_tgetstr("RI", &tp);
  396. X  IM = e_tgetstr("im", &tp);
  397. X  EI = e_tgetstr("ei", &tp);
  398. X  if (e_tgetflag("in"))
  399. X    IC = IM = 0;
  400. X  if (IC && IC[0] == '\0')
  401. X    IC = 0;
  402. X  if (CIC && CIC[0] == '\0')
  403. X    CIC = 0;
  404. X  if (IM && IM[0] == '\0')
  405. X    IM = 0;
  406. X  if (EI && EI[0] == '\0')
  407. X    EI = 0;
  408. X  if (EI == 0)
  409. X    IM = 0;
  410. X  if (IC && IM && strcmp(IC, IM) == 0)
  411. X    IC = 0;
  412. X  KS = e_tgetstr("ks", &tp);
  413. X  KE = e_tgetstr("ke", &tp);
  414. X  if (KE == 0)
  415. X    KS = 0;
  416. X  ISO2022 = e_tgetflag("G0");
  417. X  if (ISO2022)
  418. X    {
  419. X      if ((S0 = e_tgetstr("S0", &tp)) == NULL)
  420. X#ifdef TERMINFO
  421. X    S0 = "\033(%p1%c";
  422. X#else
  423. X    S0 = "\033(%.";
  424. X#endif
  425. X      if ((E0 = e_tgetstr("E0", &tp)) == NULL)
  426. X    E0 = "\033(B";
  427. X      C0 = e_tgetstr("C0", &tp);
  428. X    }
  429. X  else if ((S0 = e_tgetstr("as", &tp)) != NULL
  430. X        && (E0 = e_tgetstr("ae", &tp)) != NULL)
  431. X    {
  432. X      ISO2022 = 1;
  433. X      C0 = e_tgetstr("ac", &tp);
  434. X    }
  435. X  else
  436. X    {
  437. X      S0 = E0 = "";
  438. X      C0 = "g.h.i'j-k-l-m-n+o~p\"q-r-s_t+u+v+w+x|y<z>";
  439. X    }
  440. X  for (i = 0; i < 256; i++)
  441. X    c0_tab[i] = i;
  442. X  if (C0)
  443. X    for (i = strlen(C0)&~1; i >= 0; i-=2)
  444. X      c0_tab[C0[i]] = C0[i+1];
  445. X  debug1("ISO2022 = %d\n", ISO2022);
  446. X  /* WS changes the window size */
  447. X  WS = e_tgetstr("WS", &tp);
  448. X  VI = e_tgetstr("vi", &tp);
  449. X  VE = e_tgetstr("ve", &tp);
  450. X  VS = e_tgetstr("vs", &tp);
  451. X  PO = e_tgetstr("po", &tp);
  452. X  if (!(PF = e_tgetstr("pf", &tp)))
  453. X    PO = 0;
  454. X  debug2("terminal size is %d, %d (says TERMCAP)\n", TermcapCOLS, TermcapROWS);
  455. X  /* Termcap fields Z0 & Z1 contain width-changing sequences. */
  456. X  if ((Z0 = e_tgetstr("Z0", &tp)) != NULL
  457. X      && (Z1 = e_tgetstr("Z1", &tp)) == NULL)
  458. X    Z0 = NULL;
  459. X
  460. X  Z0width = 132;
  461. X  Z1width = 80;
  462. X
  463. X  CheckScreenSize(0);
  464. X  if ((HS = e_tgetflag("hs")) != 0)
  465. X    {
  466. X      debug("oy! we have a hardware status line, says termcap\n");
  467. X      TS = e_tgetstr("ts", &tp);
  468. X      FS = e_tgetstr("fs", &tp);
  469. X      DS = e_tgetstr("ds", &tp);
  470. X      if ((HS = e_tgetnum("ws")) <= 0)
  471. X    HS = screenwidth;
  472. X      if (!TS || !FS || !DS)
  473. X    HS = 0;
  474. X    }
  475. X  termcapHS = HS;
  476. X  if (!use_hardstatus)
  477. X    HS = 0;
  478. X
  479. X  UPcost = CalcCost(UP);
  480. X  DOcost = CalcCost(DO);
  481. X  NLcost = CalcCost(NL);
  482. X  LEcost = CalcCost(BC);
  483. X  NDcost = CalcCost(ND);
  484. X  CRcost = CalcCost(CR);
  485. X  IMcost = CalcCost(IM);
  486. X  EIcost = CalcCost(EI);
  487. X  for (i = 0; i < NKEYCAPS; i++)
  488. X    KeyCapsArr[i] = e_tgetstr(KeyCaps[i], &tp);
  489. X  MakeTermcap(0);
  490. X}
  491. X
  492. X/*
  493. X * if the adaptflag is on, we keep the size of this display, else
  494. X * we may try to restore our old window sizes.
  495. X */
  496. void
  497. InitTerm(adapt)
  498. int adapt;
  499. X{
  500. X  display = 1;
  501. X  screentop = screenbot = -1;
  502. X  PutStr(IS);
  503. X  PutStr(TI);
  504. X  if (IM && strcmp(IM, EI))
  505. X    PutStr(EI);
  506. X  insert = 0;
  507. X  if (KS && strcmp(KS, KE))
  508. X    PutStr(KE);
  509. X  keypad = 0;
  510. X  ResizeScreen((struct win *)0);
  511. X  ChangeScrollRegion(0, screenheight-1);
  512. X  PutStr(CL);
  513. X  screenx = screeny = 0;
  514. X  fflush(stdout);
  515. X  debug1("we %swant to adapt all our windows to the display\n", 
  516. X     (adapt) ? "" : "don't ");
  517. X  /* In case the size was changed by a init sequence */
  518. X  CheckScreenSize((adapt) ? 2 : 0);
  519. X}
  520. X
  521. void
  522. XFinitTerm()
  523. X{
  524. X  display = 1;
  525. X  flow = 1;
  526. X  InsertMode(0);
  527. X  KeypadMode(0);
  528. X  ResizeScreen((struct win *)0);
  529. X  ChangeScrollRegion(0, screenheight - 1);
  530. X  SaveSetAttr(0, ASCII);
  531. X  screenx = screeny = -1;
  532. X  GotoPos(0, screenheight - 1);
  533. X  PutStr(TE);
  534. X  fflush(stdout);
  535. X  if (Termcap) 
  536. X    {
  537. X      Free(Termcap);
  538. X      debug("FinitTerm: old termcap freed\n");
  539. X    }
  540. X  if (tbuf) 
  541. X    {
  542. X      Free(tbuf);
  543. X      debug("FinitTerm: old tbuf freed\n");
  544. X    }
  545. X  if (tentry) 
  546. X    {
  547. X      Free(tentry);
  548. X      debug("FinitTerm: old tentry freed\n");
  549. X    }
  550. X}
  551. X
  552. static void AddCap(s)
  553. char *s;
  554. X{
  555. X  register int n;
  556. X
  557. X  if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < 1024-4)
  558. X    {
  559. X      strcpy(Termcap + Termcaplen, "\\\n\t:");
  560. X      Termcaplen += 4;
  561. X      tcLineLen = 0;
  562. X    }
  563. X  if (Termcaplen + n < 1024)
  564. X    {
  565. X      strcpy(Termcap + Termcaplen, s);
  566. X      Termcaplen += n;
  567. X      tcLineLen += n;
  568. X    }
  569. X  else
  570. X    Msg(0, "TERMCAP overflow - sorry.");
  571. X}
  572. X
  573. char *MakeTermcap(aflag)
  574. int aflag;
  575. X{
  576. X  char buf[1024];
  577. X  register char *p, *cp, ch;
  578. X  int i;
  579. X
  580. X  if (screencap)
  581. X    {
  582. X      sprintf(Term, "TERM=screen");
  583. X      return Termcap;
  584. X    }
  585. X  if (screenterm == 0 || *screenterm == '\0')
  586. X    {
  587. X      debug("MakeTermcap sets screenterm=screen\n");
  588. X      strcpy(screenterm, "screen");
  589. X    }
  590. X  for (;;)
  591. X    {
  592. X      sprintf(Term, "TERM=");
  593. X      p = Term + 5;
  594. X      if (!aflag && (unsigned)strlen(screenterm)+strlen(termname) < MAXSTR-1)
  595. X    {
  596. X      sprintf(p, "%s.%s", screenterm, termname);
  597. X      if (tgetent(buf, p) == 1)
  598. X        break;
  599. X    }
  600. X      if (screenwidth >= 132)
  601. X    {
  602. X      sprintf(p, "%s-w", screenterm);
  603. X          if (tgetent(buf, p) == 1)
  604. X        break;
  605. X    }
  606. X      sprintf(p, "%s", screenterm);
  607. X      if (tgetent(buf, p) == 1)
  608. X    break;
  609. X      sprintf(p, "vt100");
  610. X      break;
  611. X    }
  612. X  tcLineLen = 100;    /* Force NL */
  613. X  sprintf(Termcap,
  614. X      "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", p);
  615. X  Termcaplen = strlen(Termcap);
  616. X  if (extra_outcap && *extra_outcap)
  617. X    {
  618. X      for (cp = extra_outcap; p = index(cp, ':'); cp = p)
  619. X    {
  620. X      ch = *++p;
  621. X      *p = '\0';
  622. X      AddCap(cp);
  623. X      *p = ch;
  624. X    }
  625. X      tcLineLen = 100;    /* Force NL */
  626. X    }
  627. X  if (Termcaplen + (unsigned)strlen(TermcapConst) < 1024)
  628. X    {
  629. X      strcpy(Termcap + Termcaplen, TermcapConst);
  630. X      Termcaplen += strlen(TermcapConst);
  631. X    }
  632. X  sprintf(buf, "li#%d:co#%d:", screenheight, screenwidth);
  633. X  AddCap(buf);
  634. X  if ((force_vt && !COP) || LP || !AM)
  635. X    AddCap("LP:");
  636. X  else
  637. X    AddCap("am:");
  638. X  if (VB)
  639. X    AddCap("vb=\\E[?5h\\E[?5l:");
  640. X  if (US)
  641. X    {
  642. X      AddCap("us=\\E[4m:");
  643. X      AddCap("ue=\\E[24m:");
  644. X    }
  645. X  if (SO)
  646. X    {
  647. X      AddCap("so=\\E[3m:");
  648. X      AddCap("se=\\E[23m:");
  649. X    }
  650. X  if (MB)
  651. X    AddCap("mb=\\E[5m:");
  652. X  if (MD)
  653. X    AddCap("md=\\E[1m:");
  654. X  if (MH)
  655. X    AddCap("mh=\\E[2m:");
  656. X  if (MR)
  657. X    AddCap("mr=\\E[7m:");
  658. X  if (MB || MD || MH || MR)
  659. X    AddCap("me=\\E[m:ms:");
  660. X  if ((CS && SR) || AL || CAL || aflag)
  661. X    {
  662. X      AddCap("sr=\\EM:");
  663. X      AddCap("al=\\E[L:");
  664. X      AddCap("AL=\\E[%dL:");
  665. X    }
  666. X  else if (SR)
  667. X    AddCap("sr=\\EM:");
  668. X  if (CS || DL || CDL || aflag)
  669. X    {
  670. X      AddCap("dl=\\E[M:");
  671. X      AddCap("DL=\\E[%dM:");
  672. X    }
  673. X  if (CS)
  674. X    AddCap("cs=\\E[%i%d;%dr:");
  675. X  if (DC || CDC || aflag)
  676. X    {
  677. X      AddCap("dc=\\E[P:");
  678. X      AddCap("DC=\\E[%dP:");
  679. X    }
  680. X  if (CIC || IC || IM || aflag)
  681. X    {
  682. X      AddCap("im=\\E[4h:");
  683. X      AddCap("ei=\\E[4l:");
  684. X      AddCap("mi:");
  685. X      AddCap("ic=\\E[@:");
  686. X      AddCap("IC=\\E[%d@:");
  687. X    }
  688. X  if (KS)
  689. X    AddCap("ks=\\E=:");
  690. X  if (KE)
  691. X    AddCap("ke=\\E>:");
  692. X  if (ISO2022)
  693. X    AddCap("G0:");
  694. X  if (PO)
  695. X    {
  696. X      AddCap("po=\\E[5i:");
  697. X      AddCap("pf=\\E[4i:");
  698. X    }
  699. X  if (Z0)
  700. X    {
  701. X      AddCap("Z0=\\E[?3h:");
  702. X      AddCap("Z1=\\E[?3l:");
  703. X    }
  704. X  if (WS)
  705. X    AddCap("WS=\\E[8;%d;%dt:");
  706. X  for (i = 0; i < NKEYCAPS; i++)
  707. X    {
  708. X      if (KeyCapsArr[i] == 0)
  709. X    continue;
  710. X      MakeString(KeyCaps[i], buf, sizeof(buf), KeyCapsArr[i]);
  711. X      AddCap(buf);
  712. X    }
  713. X  return Termcap;
  714. X}
  715. X
  716. static void MakeString(cap, buf, buflen, s)
  717. char *cap, *buf;
  718. int buflen;
  719. char *s;
  720. X{
  721. X  register char *p, *pmax;
  722. X  register unsigned int c;
  723. X
  724. X  p = buf;
  725. X  pmax = p + buflen - (3+4+2);
  726. X  *p++ = *cap++;
  727. X  *p++ = *cap;
  728. X  *p++ = '=';
  729. X  while ((c = *s++) && p < pmax)
  730. X    {
  731. X      switch (c)
  732. X    {
  733. X    case '\033':
  734. X      *p++ = '\\';
  735. X      *p++ = 'E';
  736. X      break;
  737. X    case ':':
  738. X      sprintf(p, "\\072");
  739. X      p += 4;
  740. X      break;
  741. X    case '^':
  742. X    case '\\':
  743. X      *p++ = '\\';
  744. X      *p++ = c;
  745. X      break;
  746. X    default:
  747. X      if (c >= 200)
  748. X        {
  749. X          sprintf(p, "\\%03o", c & 0377);
  750. X          p += 4;
  751. X        }
  752. X      else if (c < ' ')
  753. X        {
  754. X          *p++ = '^';
  755. X          *p++ = c + '@';
  756. X        }
  757. X      else
  758. X        *p++ = c;
  759. X    }
  760. X    }
  761. X  *p++ = ':';
  762. X  *p = '\0';
  763. X}
  764. X
  765. void
  766. Activate()
  767. X{
  768. X  debug("Activate()\n");
  769. X  if (display)
  770. X    RemoveStatus();
  771. X  display = fore->active = 1;
  772. X  ResizeScreen(fore);
  773. X  SetCurr(fore);
  774. X  debug3("Fore (%d) has size %dx%d", ForeNum, curr->width, curr->height);
  775. X  debug1("(%d)\n", curr->histheight);
  776. X  ChangeScrollRegion(curr->top, curr->bot);
  777. X  KeypadMode(curr->keypad);
  778. X  FlowMode(curr->flow);
  779. X  if (curr->monitor != MON_OFF)
  780. X    curr->monitor = MON_ON;
  781. X  curr->bell = BELL_OFF;
  782. X  Redisplay();
  783. X}
  784. X
  785. void
  786. ResetScreen(p)
  787. register struct win *p;
  788. X{
  789. X  register int i;
  790. X
  791. X  p->wrap = wrap;
  792. X  p->origin = 0;
  793. X  p->insert = 0;
  794. X  p->vbwait = 0;
  795. X  p->keypad = 0;
  796. X  p->top = 0;
  797. X  p->bot = p->height - 1;
  798. X  p->saved = 0;
  799. X  p->LocalAttr = 0;
  800. X  p->x = p->y = 0;
  801. X  p->state = LIT;
  802. X  p->StringType = NONE;
  803. X  p->ss = 0;
  804. X  p->LocalCharset = G0;
  805. X  bzero(p->tabs, p->width);
  806. X  for (i = 8; i < p->width; i += 8)
  807. X    p->tabs[i] = 1;
  808. X  for (i = G0; i <= G3; i++)
  809. X    p->charsets[i] = ASCII;
  810. X}
  811. X
  812. void
  813. WriteString(wp, buf, len)
  814. struct win *wp;
  815. register char *buf;
  816. int len;
  817. X{
  818. X  register int c, intermediate = 0;
  819. X
  820. X  if (!len)
  821. X    return;
  822. X  if (wp->logfp != NULL)
  823. X    if (fwrite(buf, len, 1, wp->logfp) < 1)
  824. X      {
  825. X    extern int errno;
  826. X
  827. X    Msg(errno, "Error writing logfile");
  828. X    fclose(wp->logfp);
  829. X    wp->logfp = NULL;
  830. X      }
  831. X  /*
  832. X   * SetCurr() here may prevent output, as it may set display = 0
  833. X   */
  834. X  SetCurr(wp);
  835. X  if (display)
  836. X    {
  837. X      if (!HS)
  838. X    RemoveStatus();
  839. X    }
  840. X  else if (curr->monitor == MON_ON)
  841. X    curr->monitor = MON_FOUND;
  842. X
  843. X  do
  844. X    {
  845. X      c = *buf++;
  846. X      if (c == '\0' || c == '\177')
  847. X    continue;
  848. X    NextChar:
  849. X      switch (curr->state)
  850. X    {
  851. X    case PRIN:
  852. X      switch (c)
  853. X        {
  854. X        case '\033':
  855. X          curr->state = PRINESC;
  856. X          break;
  857. X        default:
  858. X          PrintChar(c);
  859. X        }
  860. X      break;
  861. X    case PRINESC:
  862. X      switch (c)
  863. X        {
  864. X        case '[':
  865. X          curr->state = PRINCSI;
  866. X          break;
  867. X        default:
  868. X          PrintChar('\033');
  869. X          PrintChar(c);
  870. X          curr->state = PRIN;
  871. X        }
  872. X      break;
  873. X    case PRINCSI:
  874. X      switch (c)
  875. X        {
  876. X        case '4':
  877. X          curr->state = PRIN4;
  878. X          break;
  879. X        default:
  880. X          PrintChar('\033');
  881. X          PrintChar('[');
  882. X          PrintChar(c);
  883. X          curr->state = PRIN;
  884. X        }
  885. X      break;
  886. X    case PRIN4:
  887. X      switch (c)
  888. X        {
  889. X        case 'i':
  890. X          curr->state = LIT;
  891. X          PrintFlush();
  892. X          break;
  893. X        default:
  894. X          PrintChar('\033');
  895. X          PrintChar('[');
  896. X          PrintChar('4');
  897. X          PrintChar(c);
  898. X          curr->state = PRIN;
  899. X        }
  900. X      break;
  901. X    case STRESC:
  902. X      switch (c)
  903. X        {
  904. X        case '\\':
  905. X          curr->state = LIT;
  906. X          *(curr->stringp) = '\0';
  907. X          switch (curr->StringType)
  908. X        {
  909. X        case PM:
  910. X          if (!display)
  911. X            break;
  912. X          MakeStatus(curr->string);
  913. X          if (!HS && status && len > 1)
  914. X            {
  915. X              curr->outlen = len - 1;
  916. X              bcopy(buf, curr->outbuf, curr->outlen);
  917. X              return;
  918. X            }
  919. X          break;
  920. X        case DCS:
  921. X          if (display)
  922. X            printf("%s", curr->string);
  923. X          break;
  924. X        case AKA:
  925. X          if (curr->akapos == 0 && !*curr->string)
  926. X            break;
  927. X          strncpy(curr->cmd + curr->akapos, curr->string, 20);
  928. X          if (!*curr->string)
  929. X            curr->autoaka = curr->y + 1;
  930. X          break;
  931. X        default:
  932. X          break;
  933. X        }
  934. X          break;
  935. X        default:
  936. X          curr->state = ASTR;
  937. X          AddChar('\033');
  938. X          AddChar(c);
  939. X        }
  940. X      break;
  941. X    case ASTR:
  942. X      switch (c)
  943. X        {
  944. X        case '\0':
  945. X          break;
  946. X        case '\033':
  947. X          curr->state = STRESC;
  948. X          break;
  949. X        default:
  950. X          AddChar(c);
  951. X        }
  952. X      break;
  953. X    case ESC:
  954. X      switch (c)
  955. X        {
  956. X        case '[':
  957. X          curr->NumArgs = 0;
  958. X          intermediate = 0;
  959. X          bzero((char *) curr->args, MAXARGS * sizeof(int));
  960. X          curr->state = CSI;
  961. X          break;
  962. X        case ']':
  963. X          StartString(OSC);
  964. X          break;
  965. X        case '_':
  966. X          StartString(APC);
  967. X          break;
  968. X        case 'P':
  969. X          StartString(DCS);
  970. X          break;
  971. X        case '^':
  972. X          StartString(PM);
  973. X          break;
  974. X        case '"':
  975. X        case 'k':
  976. X          StartString(AKA);
  977. X          break;
  978. X        default:
  979. X          if (Special(c))
  980. X        break;
  981. X          if (c >= ' ' && c <= '/')
  982. X        intermediate = intermediate ? -1 : c;
  983. X          else if (c >= '0' && c <= '~')
  984. X        {
  985. X          DoESC(c, intermediate);
  986. X          curr->state = LIT;
  987. X        }
  988. X          else
  989. X        {
  990. X          curr->state = LIT;
  991. X          goto NextChar;
  992. X        }
  993. X        }
  994. X      break;
  995. X    case CSI:
  996. X      switch (c)
  997. X        {
  998. X        case '0':
  999. X        case '1':
  1000. X        case '2':
  1001. X        case '3':
  1002. X        case '4':
  1003. X        case '5':
  1004. X        case '6':
  1005. X        case '7':
  1006. X        case '8':
  1007. X        case '9':
  1008. X          if (curr->NumArgs < MAXARGS)
  1009. X        {
  1010. X          curr->args[curr->NumArgs] =
  1011. X            10 * curr->args[curr->NumArgs] + c - '0';
  1012. X        }
  1013. X          break;
  1014. X        case ';':
  1015. X        case ':':
  1016. X          curr->NumArgs++;
  1017. X          break;
  1018. X        default:
  1019. X          if (Special(c))
  1020. X        break;
  1021. X          if (c >= '@' && c <= '~')
  1022. X        {
  1023. X          curr->NumArgs++;
  1024. X          DoCSI(c, intermediate);
  1025. X          if (curr->state != PRIN)
  1026. X            curr->state = LIT;
  1027. X        }
  1028. X          else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
  1029. X        intermediate = intermediate ? -1 : c;
  1030. X          else
  1031. X        {
  1032. X          curr->state = LIT;
  1033. X          goto NextChar;
  1034. X        }
  1035. X        }
  1036. X      break;
  1037. X    case LIT:
  1038. X    default:
  1039. X      if (!Special(c))
  1040. X        {
  1041. X          if (c == '\033')
  1042. X        {
  1043. X          intermediate = 0;
  1044. X          curr->state = ESC;
  1045. X          if (display && lp_missing && (CIC || IC || IM))
  1046. X            {
  1047. X              RedisplayLine(blank, null, null, screenbot,
  1048. X                    cols - 2, cols - 1);
  1049. X              GotoPos(curr->x, curr->y);
  1050. X            }
  1051. X          if (curr->autoaka < 0)
  1052. X            curr->autoaka = 0;
  1053. X        }
  1054. X          else if (c < ' ')
  1055. X        break;
  1056. X          else
  1057. X        {
  1058. X          NewRendition(curr->LocalAttr);
  1059. X          NewCharset(curr->charsets[(curr->ss) ? curr->ss :
  1060. X                         curr->LocalCharset]);
  1061. X          if (curr->x < cols - 1)
  1062. X            {
  1063. X              if (curr->insert)
  1064. X            InsertAChar(c);
  1065. X              else
  1066. X            {
  1067. X              if (display)
  1068. X                PUTCHAR(c);
  1069. X              SetChar(c);
  1070. X            }
  1071. X              curr->x++;
  1072. X            }
  1073. X          else if (curr->x == cols - 1)
  1074. X            {
  1075. X              if (curr->wrap && (LP || !force_vt || COP))
  1076. X            {
  1077. X              if (display)
  1078. X                RAW_PUTCHAR(c);
  1079. X              SetChar(c);
  1080. X              if (AM && !LP)
  1081. X                {
  1082. X                  curr->x = 0; /* terminal auto-wrapped */
  1083. X                  LineFeed(0);
  1084. X                }
  1085. X              else
  1086. X                curr->x++;
  1087. X            }
  1088. X              else
  1089. X            {
  1090. X              if (display)
  1091. X                {
  1092. X                  if (LP || curr->y != screenbot)
  1093. X                {
  1094. X                  RAW_PUTCHAR(c);
  1095. X                  GotoPos(curr->x, curr->y);
  1096. X                }
  1097. X                  else
  1098. X                CheckLP(c);
  1099. X                }
  1100. X              SetChar(c);
  1101. X              if (curr->wrap)
  1102. X                curr->x++;
  1103. X            }
  1104. X            }
  1105. X          else
  1106. X            {
  1107. X              LineFeed(2); /* cr+lf, handle LP */
  1108. X              if (curr->insert)
  1109. X            InsertAChar(c);
  1110. X              else
  1111. X            {
  1112. X              if (display)
  1113. X                PUTCHAR(c);
  1114. X              SetChar(c);
  1115. X            }
  1116. X              curr->x = 1;
  1117. X            }
  1118. X          if (curr->ss)
  1119. X            {
  1120. X              NewCharset(curr->charsets[curr->LocalCharset]);
  1121. X              curr->ss = 0;
  1122. X            }
  1123. X        }
  1124. X        }
  1125. X    }
  1126. X    } while (--len);
  1127. X  curr->outlen = 0;
  1128. X  if (curr->state == PRIN)
  1129. X    PrintFlush();
  1130. X}
  1131. X
  1132. static int Special(c)
  1133. register int c;
  1134. X{
  1135. X  switch (c)
  1136. X    {
  1137. X    case '\b':
  1138. X      BackSpace();
  1139. X      return 1;
  1140. X    case '\r':
  1141. X      Return();
  1142. X      return 1;
  1143. X    case '\n':
  1144. X      if (curr->autoaka)
  1145. X    FindAKA();
  1146. X      LineFeed(1);
  1147. X      return 1;
  1148. X    case '\007':
  1149. X      if (!visual_bell)
  1150. X    PutStr(BL);
  1151. X      else
  1152. X    {
  1153. X      if (!VB)
  1154. X        curr->bell = BELL_VISUAL;
  1155. X      else
  1156. X        PutStr(VB);
  1157. X    }
  1158. X      if (!display)
  1159. X    curr->bell = BELL_ON;
  1160. X      return 1;
  1161. X    case '\t':
  1162. X      ForwardTab();
  1163. X      return 1;
  1164. X    case '\017':        /* SI */
  1165. X      MapCharset(G0);
  1166. X      return 1;
  1167. X    case '\016':        /* SO */
  1168. X      MapCharset(G1);
  1169. X      return 1;
  1170. X    }
  1171. X  return 0;
  1172. X}
  1173. X
  1174. static void DoESC(c, intermediate)
  1175. int c, intermediate;
  1176. X{
  1177. X  switch (intermediate)
  1178. X    {
  1179. X    case 0:
  1180. X      switch (c)
  1181. X    {
  1182. X    case 'E':
  1183. X      LineFeed(2);
  1184. X      break;
  1185. X    case 'D':
  1186. X      LineFeed(1);
  1187. X      break;
  1188. X    case 'M':
  1189. X      ReverseLineFeed();
  1190. X      break;
  1191. X    case 'H':
  1192. X      curr->tabs[curr->x] = 1;
  1193. X      break;
  1194. X    case 'Z':        /* jph: Identify as VT100 */
  1195. X      Report(curr, "\033[?%d;%dc", 1, 2);
  1196. X      break;
  1197. X    case '7':
  1198. X      SaveCursor();
  1199. X      break;
  1200. X    case '8':
  1201. X      RestoreCursor();
  1202. X      break;
  1203. X    case 'c':
  1204. X      ClearScreen();
  1205. X      ResetScreen(curr);
  1206. X      NewRendition(0);
  1207. X      NewCharset(ASCII);
  1208. X      InsertMode(0);
  1209. X      KeypadMode(0);
  1210. X      ChangeScrollRegion(0, rows-1);
  1211. X      break;
  1212. X    case '=':
  1213. X      KeypadMode(1);
  1214. X      curr->keypad = 1;
  1215. X      if (curr->autoflow)
  1216. X        FlowMode(curr->flow = 0);
  1217. X      break;
  1218. X    case '>':
  1219. X      KeypadMode(0);
  1220. X      curr->keypad = 0;
  1221. X      if (curr->autoflow)
  1222. X        FlowMode(curr->flow = 1);
  1223. X      break;
  1224. X    case 'n':        /* LS2 */
  1225. X      MapCharset(G2);
  1226. X      break;
  1227. X    case 'o':        /* LS3 */
  1228. X      MapCharset(G3);
  1229. X      break;
  1230. X    case 'N':        /* SS2 */
  1231. X      if (curr->charsets[curr->LocalCharset] != curr->charsets[G2])
  1232. X        curr->ss = G2;
  1233. X      else
  1234. X        curr->ss = 0;
  1235. X      break;
  1236. X    case 'O':        /* SS3 */
  1237. X      if (curr->charsets[curr->LocalCharset] != curr->charsets[G3])
  1238. X        curr->ss = G3;
  1239. X      else
  1240. X        curr->ss = 0;
  1241. X      break;
  1242. X    }
  1243. X      break;
  1244. X    case '#':
  1245. X      switch (c)
  1246. X    {
  1247. X    case '8':
  1248. X      FillWithEs();
  1249. X      break;
  1250. X    }
  1251. X      break;
  1252. X    case '(':
  1253. X      DesignateCharset(c, G0);
  1254. X      break;
  1255. X    case ')':
  1256. X      DesignateCharset(c, G1);
  1257. X      break;
  1258. X    case '*':
  1259. X      DesignateCharset(c, G2);
  1260. X      break;
  1261. X    case '+':
  1262. X      DesignateCharset(c, G3);
  1263. X      break;
  1264. X    }
  1265. X}
  1266. X
  1267. static void DoCSI(c, intermediate)
  1268. int c, intermediate;
  1269. X{
  1270. X  register int i, a1 = curr->args[0], a2 = curr->args[1];
  1271. X
  1272. X  if (curr->NumArgs > MAXARGS)
  1273. X    curr->NumArgs = MAXARGS;
  1274. X  switch (intermediate)
  1275. X    {
  1276. X    case 0:
  1277. X      switch (c)
  1278. X    {
  1279. X    case 'H':
  1280. X    case 'f':
  1281. X      if (a1 < 1)
  1282. X        a1 = 1;
  1283. X      if (curr->origin)
  1284. X        a1 += curr->top;
  1285. X      if (a1 > rows)
  1286. X        a1 = rows;
  1287. X      if (a2 < 1)
  1288. X        a2 = 1;
  1289. X      if (a2 > cols)
  1290. X        a2 = cols;
  1291. X      GotoPos(--a2, --a1);
  1292. X      curr->x = a2;
  1293. X      curr->y = a1;
  1294. X      if (curr->autoaka)
  1295. X        curr->autoaka = a1 + 1;
  1296. X      break;
  1297. X    case 'J':
  1298. X      if (a1 < 0 || a1 > 2)
  1299. X        a1 = 0;
  1300. X      switch (a1)
  1301. X        {
  1302. X        case 0:
  1303. X          ClearToEOS();
  1304. X          break;
  1305. X        case 1:
  1306. X          ClearFromBOS();
  1307. X          break;
  1308. X        case 2:
  1309. X          ClearScreen();
  1310. X          GotoPos(curr->x, curr->y);
  1311. X          break;
  1312. X        }
  1313. X      break;
  1314. X    case 'K':
  1315. X      if (a1 < 0 || a1 > 2)
  1316. X        a1 %= 3;
  1317. X      switch (a1)
  1318. X        {
  1319. X        case 0:
  1320. X          ClearToEOL();
  1321. X          break;
  1322. X        case 1:
  1323. X          ClearFromBOL();
  1324. X          break;
  1325. X        case 2:
  1326. X          ClearLine();
  1327. X          break;
  1328. X        }
  1329. X      break;
  1330. X    case 'A':
  1331. X      CursorUp(a1 ? a1 : 1);
  1332. X      break;
  1333. X    case 'B':
  1334. X      CursorDown(a1 ? a1 : 1);
  1335. X      break;
  1336. X    case 'C':
  1337. X      CursorRight(a1 ? a1 : 1);
  1338. X      break;
  1339. X    case 'D':
  1340. X      CursorLeft(a1 ? a1 : 1);
  1341. X      break;
  1342. X    case 'm':
  1343. X      SelectRendition();
  1344. X      break;
  1345. X    case 'g':
  1346. X      if (a1 == 0)
  1347. X        curr->tabs[curr->x] = 0;
  1348. X      else if (a1 == 3)
  1349. X        bzero(curr->tabs, cols);
  1350. X      break;
  1351. X    case 'r':
  1352. X      if (!a1)
  1353. X        a1 = 1;
  1354. X      if (!a2)
  1355. X        a2 = rows;
  1356. X      if (a1 < 1 || a2 > rows || a1 >= a2)
  1357. X        break;
  1358. X      curr->top = a1 - 1;
  1359. X      curr->bot = a2 - 1;
  1360. X      ChangeScrollRegion(curr->top, curr->bot);
  1361. X      if (curr->origin)
  1362. X        {
  1363. X          GotoPos(0, curr->top);
  1364. X          curr->y = curr->top;
  1365. X          curr->x = 0;
  1366. X        }
  1367. X      else
  1368. X        {
  1369. X          GotoPos(0, 0);
  1370. X          curr->y = curr->x = 0;
  1371. X        }
  1372. X      break;
  1373. X    case 's':
  1374. X      SaveCursor();
  1375. X      break;
  1376. X    case 't':
  1377. X      if (a1 != 8)
  1378. X        break;
  1379. X      a1 = curr->args[2];
  1380. X      if (a1 < 1)
  1381. X        a1 = curr->width;
  1382. X      if (a2 < 1)
  1383. X        a2 = curr->height;
  1384. X      if (WS == NULL)
  1385. X        {
  1386. X          a2 = curr->height;
  1387. X          if (Z0 == NULL || (a1 != Z0width && a1 != Z1width))
  1388. X            a1 = curr->width;
  1389. X         }
  1390. X      if (a1 == curr->width && a2 == curr->height)
  1391. X        break;
  1392. X          ChangeWindowSize(curr, a1, a2);
  1393. X      SetCurr(curr);
  1394. X      if (display)
  1395. X        Activate();
  1396. X      break;
  1397. X    case 'u':
  1398. X      RestoreCursor();
  1399. X      break;
  1400. X    case 'I':
  1401. X      if (!a1)
  1402. X        a1 = 1;
  1403. X      while (a1--)
  1404. X        ForwardTab();
  1405. X      break;
  1406. X    case 'Z':
  1407. X      if (!a1)
  1408. X        a1 = 1;
  1409. X      while (a1--)
  1410. X        BackwardTab();
  1411. X      break;
  1412. X    case 'L':
  1413. X      InsertLine(a1 ? a1 : 1);
  1414. X      break;
  1415. X    case 'M':
  1416. X      DeleteLine(a1 ? a1 : 1);
  1417. X      break;
  1418. X    case 'P':
  1419. X      DeleteChar(a1 ? a1 : 1);
  1420. X      break;
  1421. X    case '@':
  1422. X      InsertChar(a1 ? a1 : 1);
  1423. X      break;
  1424. X    case 'h':
  1425. X      ASetMode(1);
  1426. X      break;
  1427. X    case 'l':
  1428. X      ASetMode(0);
  1429. X      break;
  1430. X    case 'i':
  1431. X      if (PO && a1 == 5)
  1432. X        {
  1433. X          curr->stringp = curr->string;
  1434. X          curr->state = PRIN;
  1435. X        }
  1436. X      break;
  1437. X    case 'n':
  1438. X      if (a1 == 6)        /* Report cursor position */
  1439. X        Report(curr, "\033[%d;%dR", curr->y + 1, curr->x + 1);
  1440. X      break;
  1441. X    case 'c':        /* Identify as VT100 */
  1442. X      Report(curr, "\033[?%d;%dc", 1, 2);
  1443. X      break;
  1444. X    }
  1445. X      break;
  1446. X    case '?':
  1447. X      debug2("\\E[?%d%c\n",a1,c);
  1448. X      if (c != 'h' && c != 'l')
  1449. X    break;
  1450. X      i = (c == 'h');
  1451. X      switch (a1)
  1452. X    {
  1453. X    case 3:
  1454. X      i = (i ? Z0width : Z1width);
  1455. X      if ((Z0 || WS) && curr->width != i)
  1456. X        {
  1457. X              ChangeWindowSize(curr, i, curr->height);
  1458. X          SetCurr(curr);
  1459. X          if (display)
  1460. X        Activate();
  1461. X        }
  1462. X      break;
  1463. X    case 5:
  1464. X      if (i)
  1465. X        curr->vbwait = 1;
  1466. X      else
  1467. X        {
  1468. X          if (curr->vbwait)
  1469. X        PutStr(VB);
  1470. X          curr->vbwait = 0;
  1471. X        }
  1472. X      break;
  1473. X    case 6:
  1474. X      if ((curr->origin = i) != 0)
  1475. X        {
  1476. X          GotoPos(0, curr->top);
  1477. X          curr->y = curr->top;
  1478. X          curr->x = 0;
  1479. X        }
  1480. X      else
  1481. X        {
  1482. X          GotoPos(0, 0);
  1483. X          curr->y = curr->x = 0;
  1484. X        }
  1485. X      break;
  1486. X    case 7:
  1487. X      curr->wrap = i;
  1488. X      break;
  1489. X    case 35:
  1490. X      debug1("Cursor %svisible\n", i?"in":"");
  1491. X      curr->cursor_invisible = i;
  1492. X      break;
  1493. X    }
  1494. X      break;
  1495. X    }
  1496. X}
  1497. X
  1498. void
  1499. INSERTCHAR(c)
  1500. int c;
  1501. X{
  1502. X  if (!insert && (IC || CIC))
  1503. X    {
  1504. X      if (IC)
  1505. X        PutStr(IC);
  1506. X      else
  1507. X        CPutStr(CIC, 1);
  1508. X      RAW_PUTCHAR(c);
  1509. X      return;
  1510. X    }
  1511. X  InsertMode(1);
  1512. X  if (insert)
  1513. X    RAW_PUTCHAR(c);
  1514. X  else
  1515. X    RefreshLine(screeny, screenx, screenwidth-1);
  1516. X}
  1517. X
  1518. void
  1519. PUTCHAR(c)
  1520. int c;
  1521. X{
  1522. X  if (insert)
  1523. X    InsertMode(0);
  1524. X  RAW_PUTCHAR(c);
  1525. X}
  1526. X
  1527. X/*
  1528. X * RAW_PUTCHAR() is for all text that will be displayed.
  1529. X * NOTE, that charset Nr. 0 has a conversion table, but c1, c2, ... don't.
  1530. X */
  1531. X
  1532. static void
  1533. RAW_PUTCHAR(c)
  1534. int c;
  1535. X{
  1536. X  if (GlobalCharset == '0')
  1537. X    putchar(c0_tab[c]);
  1538. X  else
  1539. X    putchar(c);
  1540. X  if (screenx < screenwidth - 1)
  1541. X    screenx++;
  1542. X  else
  1543. X    {
  1544. X      screenx++;
  1545. X      if ((AM && !LP) || screenx > screenwidth)
  1546. X    {
  1547. X      screenx -= screenwidth;
  1548. X      if (screeny < screenheight-1 && screeny != screenbot)
  1549. X        screeny++;
  1550. X    }
  1551. X    }
  1552. X}
  1553. X
  1554. void
  1555. PutChar(c)
  1556. int c;
  1557. X{
  1558. X  /* this PutChar for ESC-sequences only */
  1559. X  putchar(c);
  1560. X}
  1561. X
  1562. void
  1563. PutStr(s)
  1564. char *s;
  1565. X{
  1566. X  if (display && s)
  1567. X    tputs(s, 1, PutChar);
  1568. X}
  1569. X
  1570. static void CPutStr(s, c)
  1571. char *s;
  1572. int c;
  1573. X{
  1574. X  if (display && s)
  1575. X    tputs(tgoto(s, 0, c), 1, PutChar);
  1576. X}
  1577. X
  1578. static void SetChar(c)
  1579. register int c;
  1580. X{
  1581. X  register struct win *p = curr;
  1582. X
  1583. X  p->image[p->y][p->x] = c;
  1584. X  p->attr[p->y][p->x] = p->LocalAttr;
  1585. X  p->font[p->y][p->x] = p->charsets[p->ss ? p->ss : p->LocalCharset];
  1586. X}
  1587. X
  1588. static void StartString(type)
  1589. enum string_t type;
  1590. X{
  1591. X  curr->StringType = type;
  1592. X  curr->stringp = curr->string;
  1593. X  curr->state = ASTR;
  1594. X}
  1595. X
  1596. static void AddChar(c)
  1597. int c;
  1598. X{
  1599. X  if (curr->stringp >= curr->string + MAXSTR - 1)
  1600. X    curr->state = LIT;
  1601. X  else
  1602. X    *(curr->stringp)++ = c;
  1603. X}
  1604. X
  1605. static void PrintChar(c)
  1606. int c;
  1607. X{
  1608. X  if (curr->stringp >= curr->string + MAXSTR - 1)
  1609. X    PrintFlush();
  1610. X  *(curr->stringp)++ = c;
  1611. X}
  1612. X
  1613. static void PrintFlush()
  1614. X{
  1615. X  if (curr->stringp > curr->string)
  1616. X    {
  1617. X      tputs(PO, 1, PutChar);
  1618. X      (void) fflush(stdout);
  1619. X      (void) write(1, curr->string, curr->stringp - curr->string);
  1620. X      tputs(PF, 1, PutChar);
  1621. X      (void) fflush(stdout);
  1622. X      curr->stringp = curr->string;
  1623. X    }
  1624. X}
  1625. X
  1626. X/* Insert mode is a toggle on some terminals, so we need this hack:
  1627. X */
  1628. void
  1629. InsertMode(on)
  1630. int on;
  1631. X{
  1632. X  if (display && on != insert && IM)
  1633. X    {
  1634. X      insert = on;
  1635. X      if (insert)
  1636. X    PutStr(IM);
  1637. X      else
  1638. X    PutStr(EI);
  1639. X    }
  1640. X}
  1641. X
  1642. X/* ...and maybe keypad application mode is a toggle, too:
  1643. X */
  1644. static void KeypadMode(on)
  1645. int on;
  1646. X{
  1647. X  if (display && keypad != on && KS)
  1648. X    {
  1649. X      keypad = on;
  1650. X      if (keypad)
  1651. X    PutStr(KS);
  1652. X      else
  1653. X    PutStr(KE);
  1654. X    }
  1655. X}
  1656. X
  1657. static void FlowMode(on)
  1658. int on;
  1659. X{
  1660. X  if (display && flow != on)
  1661. X    {
  1662. X      flow = on;
  1663. X      SetFlow(on);
  1664. X    }
  1665. X}
  1666. X
  1667. void
  1668. ToggleFlow()
  1669. X{
  1670. X  flow = fore->flow = !fore->flow;
  1671. X  SetFlow(flow);
  1672. X}
  1673. X
  1674. static void DesignateCharset(c, n)
  1675. int c, n;
  1676. X{
  1677. X  curr->ss = 0;
  1678. X  if (c == 'B')
  1679. X    c = ASCII;
  1680. X  if (curr->charsets[n] != c)
  1681. X    {
  1682. X      curr->charsets[n] = c;
  1683. X      if (curr->LocalCharset == n)
  1684. X    NewCharset(c);
  1685. X    }
  1686. X}
  1687. X
  1688. static void MapCharset(n)
  1689. int n;
  1690. X{
  1691. X  curr->ss = 0;
  1692. X  if (curr->LocalCharset != n)
  1693. X    {
  1694. X      curr->LocalCharset = n;
  1695. X      NewCharset(curr->charsets[n]);
  1696. X    }
  1697. X}
  1698. X
  1699. void
  1700. NewCharset(new)
  1701. int new;
  1702. X{
  1703. X  if (!display || GlobalCharset == new)
  1704. X    return;
  1705. X  GlobalCharset = new;
  1706. X  if (new == ASCII)
  1707. X    PutStr(E0);
  1708. X  else
  1709. X    CPutStr(S0, new);
  1710. X}
  1711. X
  1712. static void SaveCursor()
  1713. X{
  1714. X  curr->saved = 1;
  1715. X  curr->Saved_x = curr->x;
  1716. X  curr->Saved_y = curr->y;
  1717. X  curr->SavedLocalAttr = curr->LocalAttr;
  1718. X  curr->SavedLocalCharset = curr->LocalCharset;
  1719. X  bcopy((char *) curr->charsets, (char *) curr->SavedCharsets,
  1720. X    4 * sizeof(int));
  1721. X}
  1722. X
  1723. static void RestoreCursor()
  1724. X{
  1725. X  if (curr->saved)
  1726. X    {
  1727. X      GotoPos(curr->Saved_x, curr->Saved_y);
  1728. X      curr->x = curr->Saved_x;
  1729. X      curr->y = curr->Saved_y;
  1730. X      curr->LocalAttr = curr->SavedLocalAttr;
  1731. X      NewRendition(curr->LocalAttr);
  1732. X      bcopy((char *) curr->SavedCharsets, (char *) curr->charsets,
  1733. X        4 * sizeof(int));
  1734. X      curr->LocalCharset = curr->SavedLocalCharset;
  1735. X      NewCharset(curr->charsets[curr->LocalCharset]);
  1736. X    }
  1737. X}
  1738. X
  1739. X/*ARGSUSED*/
  1740. static void CountChars(c)
  1741. int c;
  1742. X{
  1743. X  StrCost++;
  1744. X}
  1745. X
  1746. static int CalcCost(s)
  1747. register char *s;
  1748. X{
  1749. X  if (s)
  1750. X    {
  1751. X      StrCost = 0;
  1752. X      tputs(s, 1, CountChars);
  1753. X      return StrCost;
  1754. X    }
  1755. X  else
  1756. X    return EXPENSIVE;
  1757. X}
  1758. X
  1759. void
  1760. GotoPos(x2, y2)
  1761. int x2, y2;
  1762. X{
  1763. X  register int dy, dx, x1, y1;
  1764. X  register int costx, costy;
  1765. X  register int m;
  1766. X  register char *s;
  1767. X  int CMcost;
  1768. X  enum move_t xm = M_NONE, ym = M_NONE;
  1769. X
  1770. X  if (!display)
  1771. X    return;
  1772. X
  1773. X  x1 = screenx;
  1774. X  y1 = screeny;
  1775. X
  1776. X  if (x1 == screenwidth)
  1777. X    if (LP && AM)
  1778. X      x1 = -1;        /* don't know how the terminal treats this */
  1779. X    else
  1780. X      x1--;
  1781. X  if (x2 == screenwidth)
  1782. X    x2--;
  1783. X  dx = x2 - x1;
  1784. X  dy = y2 - y1;
  1785. X  if (dy == 0 && dx == 0)
  1786. X    {
  1787. X      return;
  1788. X    }
  1789. X  if (!MS && GlobalAttr)    /* Save to move in SO mode ? */
  1790. X    NewRendition(0);
  1791. X  if (y1 < 0            /* don't know the y position */
  1792. X      || (y2 > screenbot && y1 <= screenbot)    /* have to cross border */
  1793. X      || (y2 < screentop && y1 >= screentop))    /* of scrollregion ?    */
  1794. X    {
  1795. X    DoCM:
  1796. X      if (HO && !x2 && !y2)
  1797. X        PutStr(HO);
  1798. X      else
  1799. X        PutStr(tgoto(CM, x2, y2));
  1800. X      screenx = x2;
  1801. X      screeny = y2;
  1802. X      return;
  1803. X    }
  1804. X  /* Calculate CMcost */
  1805. X  if (HO && !x2 && !y2)
  1806. X    s = HO;
  1807. X  else
  1808. X    s = tgoto(CM, x2, y2);
  1809. X  CMcost = CalcCost(s);
  1810. X
  1811. X  /* Calculate the cost to move the cursor to the right x position */
  1812. X  costx = EXPENSIVE;
  1813. X  if (x1 >= 0)    /* relativ x positioning only if we know where we are */
  1814. X    {
  1815. X      if (dx > 0)
  1816. X    {
  1817. X      if (CRI && (dx > 1 || !ND))
  1818. X        {
  1819. X          costx = CalcCost(tgoto(CRI, 0, dx));
  1820. X          xm = M_CRI;
  1821. X        }
  1822. X      if ((m = NDcost * dx) < costx)
  1823. X        {
  1824. X          costx = m;
  1825. X          xm = M_RI;
  1826. X        }
  1827. X      /* Speedup: dx <= Rewrite() */
  1828. X      if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx)
  1829. X        {
  1830. X          costx = m;
  1831. X          xm = M_RW;
  1832. X        }
  1833. X    }
  1834. X      else if (dx < 0)
  1835. X    {
  1836. X      if (CLE && (dx < -1 || !BC))
  1837. X        {
  1838. X          costx = CalcCost(tgoto(CLE, 0, -dx));
  1839. X          xm = M_CLE;
  1840. X        }
  1841. X      if ((m = -dx * LEcost) < costx)
  1842. X        {
  1843. X          costx = m;
  1844. X          xm = M_LE;
  1845. X        }
  1846. X    }
  1847. X      else
  1848. X    costx = 0;
  1849. X    }
  1850. X  /* Speedup: Rewrite() >= x2 */
  1851. X  if (x2 + CRcost < costx && (m = Rewrite(y1, 0, x2, 0) + CRcost) < costx)
  1852. X    {
  1853. X      costx = m;
  1854. X      xm = M_CR;
  1855. X    }
  1856. X
  1857. X  /* Check if it is already cheaper to do CM */
  1858. X  if (costx >= CMcost)
  1859. X    goto DoCM;
  1860. X
  1861. X  /* Calculate the cost to move the cursor to the right y position */
  1862. X  costy = EXPENSIVE;
  1863. X  if (dy > 0)
  1864. X    {
  1865. X      if (CDO && dy > 1)    /* DO & NL are always != 0 */
  1866. X    {
  1867. X      costy = CalcCost(tgoto(CDO, 0, dy));
  1868. X      ym = M_CDO;
  1869. X    }
  1870. X      if ((m = dy * ((x2 == 0) ? NLcost : DOcost)) < costy)
  1871. X    {
  1872. X      costy = m;
  1873. X      ym = M_DO;
  1874. X    }
  1875. X    }
  1876. X  else if (dy < 0)
  1877. X    {
  1878. X      if (CUP && (dy < -1 || !UP))
  1879. X    {
  1880. X      costy = CalcCost(tgoto(CUP, 0, -dy));
  1881. X      ym = M_CUP;
  1882. X    }
  1883. X      if ((m = -dy * UPcost) < costy)
  1884. X    {
  1885. X      costy = m;
  1886. X      ym = M_UP;
  1887. X    }
  1888. X    }
  1889. X  else
  1890. X    costy = 0;
  1891. X
  1892. X  /* Finally check if it is cheaper to do CM */
  1893. X  if (costx + costy >= CMcost)
  1894. X    goto DoCM;
  1895. X
  1896. X  switch (xm)
  1897. X    {
  1898. X    case M_LE:
  1899. X      while (dx++ < 0)
  1900. X    PutStr(BC);
  1901. X      break;
  1902. X    case M_CLE:
  1903. X      CPutStr(CLE, -dx);
  1904. X      break;
  1905. X    case M_RI:
  1906. X      while (dx-- > 0)
  1907. X    PutStr(ND);
  1908. X      break;
  1909. X    case M_CRI:
  1910. X      CPutStr(CRI, dx);
  1911. X      break;
  1912. X    case M_CR:
  1913. X      PutStr(CR);
  1914. X      screenx = 0;
  1915. X      x1 = 0;
  1916. X      /* FALLTHROUGH */
  1917. X    case M_RW:
  1918. X      if (x1 < x2)
  1919. X    Rewrite(y1, x1, x2, 1);
  1920. X      break;
  1921. X    default:
  1922. X      break;
  1923. X    }
  1924. X  switch (ym)
  1925. X    {
  1926. X    case M_UP:
  1927. X      while (dy++ < 0)
  1928. X    PutStr(UP);
  1929. X      break;
  1930. X    case M_CUP:
  1931. X      CPutStr(CUP, -dy);
  1932. X      break;
  1933. X    case M_DO:
  1934. X      s =  (x2 == 0) ? NL : DO;
  1935. X      while (dy-- > 0)
  1936. X    PutStr(s);
  1937. X      break;
  1938. X    case M_CDO:
  1939. X      CPutStr(CDO, dy);
  1940. X      break;
  1941. X    default:
  1942. X      break;
  1943. X    }
  1944. X  screenx = x2;
  1945. X  screeny = y2;
  1946. X}
  1947. X
  1948. static int
  1949. Rewrite(y, x1, x2, doit)
  1950. int y, x1, x2, doit;
  1951. X{
  1952. X  register int cost, dx;
  1953. X  register char *p, *f, *i;
  1954. X
  1955. X  if (x1 == x2)
  1956. X    return(0);
  1957. X  if (in_ovl)
  1958. X    {
  1959. X      if (ovl_Rewrite == 0)
  1960. X        return EXPENSIVE;
  1961. X      else
  1962. X        return ((*ovl_Rewrite)(y, x1, x2, doit));
  1963. X    }
  1964. X  dx = x2 - x1;
  1965. X  if (doit)
  1966. X    {
  1967. X      i = curr->image[y] + x1;
  1968. X      while (dx-- > 0)
  1969. X    PUTCHAR(*i++);
  1970. X      return(0);
  1971. X    }
  1972. X  p = curr->attr[y] + x1;
  1973. X  f = curr->font[y] + x1;
  1974. X
  1975. X  cost = dx = x2 - x1;
  1976. X  if (insert)
  1977. X    cost += EIcost + IMcost;
  1978. X  while(dx-- > 0)
  1979. X    {
  1980. X      if (*p++ != GlobalAttr || *f++ != GlobalCharset)
  1981. X    return EXPENSIVE;
  1982. X    }
  1983. X  return cost;
  1984. X}
  1985. X
  1986. static void BackSpace()
  1987. X{
  1988. X  if (curr->x > 0)
  1989. X    {
  1990. X      curr->x--;
  1991. X    }
  1992. X  else if (curr->wrap && curr->y > 0)
  1993. X    {
  1994. X      curr->x = cols - 1;
  1995. X      curr->y--;
  1996. X    }
  1997. X  if (display)
  1998. X    GotoPos(curr->x, curr->y);
  1999. X}
  2000. X
  2001. static void Return()
  2002. X{
  2003. X  if (curr->x > 0)
  2004. X    {
  2005. X      curr->x = 0;
  2006. X      if (display)
  2007. X        GotoPos(curr->x, curr->y);
  2008. X    }
  2009. X}
  2010. X
  2011. static void LineFeed(out_mode)
  2012. int out_mode;
  2013. X{
  2014. X  /* out_mode: 0=no-output lf, 1=lf, 2=cr+lf */
  2015. X  if (out_mode == 2)
  2016. X    curr->x = 0;
  2017. X  if (curr->y != curr->bot)        /* Don't scroll */
  2018. X    {
  2019. X      if (curr->y < rows-1)
  2020. X    curr->y++;
  2021. X      if (out_mode && display)
  2022. X    GotoPos(curr->x, curr->y);
  2023. X      return;
  2024. X    }
  2025. X  ScrollUpMap(1);
  2026. X  if (curr->autoaka > 1)
  2027. X    curr->autoaka--;
  2028. X  if (out_mode && display)
  2029. X    {
  2030. X      ScrollRegion(curr->top, curr->bot, 1);
  2031. X      GotoPos(curr->x, curr->y);
  2032. X    }
  2033. X}
  2034. X
  2035. static void ReverseLineFeed()
  2036. X{
  2037. X  if (curr->y == curr->top)
  2038. X    {
  2039. X      ScrollDownMap(1);
  2040. X      if (!display)
  2041. X    return;
  2042. X      ScrollRegion(curr->top, curr->bot, -1);
  2043. X      GotoPos(curr->x, curr->y);
  2044. X    }
  2045. X  else if (curr->y > 0)
  2046. X    CursorUp(1);
  2047. X}
  2048. X
  2049. static void InsertAChar(c)
  2050. int c;
  2051. X{
  2052. X  register int y = curr->y, x = curr->x;
  2053. X
  2054. X  if (x == cols)
  2055. X    x--;
  2056. X  bcopy(curr->image[y], OldImage, cols);
  2057. X  bcopy(curr->attr[y], OldAttr, cols);
  2058. X  bcopy(curr->font[y], OldFont, cols);
  2059. X  bcopy(curr->image[y] + x, curr->image[y] + x + 1, cols - x - 1);
  2060. X  bcopy(curr->attr[y] + x, curr->attr[y] + x + 1, cols - x - 1);
  2061. X  bcopy(curr->font[y] + x, curr->font[y] + x + 1, cols - x - 1);
  2062. X  SetChar(c);
  2063. X  if (!display)
  2064. X    return;
  2065. X  if (CIC || IC || IM)
  2066. X    {
  2067. X      InsertMode(curr->insert);
  2068. X      INSERTCHAR(c);
  2069. X      if (y == screenbot)
  2070. X    lp_missing = 0;
  2071. X    }
  2072. X  else
  2073. X    {
  2074. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2075. X      GotoPos(++x, y);
  2076. X    }
  2077. X}
  2078. X
  2079. static void InsertChar(n)
  2080. int n;
  2081. X{
  2082. X  register int i, y = curr->y, x = curr->x;
  2083. X
  2084. X  if (n <= 0)
  2085. X    return;
  2086. X  /*
  2087. X   * The termcap manual states that only one of IM and IC is
  2088. X   * to be defined unless the terminal needs both sequences.
  2089. X   * We don't like this because we think that there may be cases
  2090. X   * where it is preferable to send IC instead of IM/EI.
  2091. X   * The hack is to ignore the IC sequence if we are already
  2092. X   * in insert mode, so that programs which follow the termcap
  2093. X   * guidelines still work. (I don't believe that there are
  2094. X   * terminals which need IC in the insert mode. Why switch to
  2095. X   * insert mode if you must send IC before every character ???)
  2096. X   */
  2097. X  if (curr->insert)
  2098. X    return;
  2099. X  if (x == cols)
  2100. X    --x;
  2101. X  bcopy(curr->image[y], OldImage, cols);
  2102. X  bcopy(curr->attr[y], OldAttr, cols);
  2103. X  bcopy(curr->font[y], OldFont, cols);
  2104. X  if (n > cols - x)
  2105. X    n = cols - x;
  2106. X  bcopy(curr->image[y] + x, curr->image[y] + x + n, cols - x - n);
  2107. X  bcopy(curr->attr[y] + x, curr->attr[y] + x + n, cols - x - n);
  2108. X  bcopy(curr->font[y] + x, curr->font[y] + x + n, cols - x - n);
  2109. X  ClearInLine(0, y, x, x + n - 1);
  2110. X  if (!display)
  2111. X    return;
  2112. X  if (IC || CIC || IM)
  2113. X    {
  2114. X      if (y == screenbot)
  2115. X    lp_missing = 0;
  2116. X      if (!insert)
  2117. X    {
  2118. X      if (n == 1 && IC)
  2119. X        {
  2120. X          PutStr(IC);
  2121. X          return;
  2122. X            }
  2123. X      if (CIC)
  2124. X        {
  2125. X          CPutStr(CIC, n);
  2126. X          return;
  2127. X            }
  2128. X    }
  2129. X      InsertMode(1);
  2130. X      for (i = n; i--; )
  2131. X    INSERTCHAR(' ');
  2132. X      GotoPos(x, y);
  2133. X    }
  2134. X  else
  2135. X    {
  2136. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2137. X      GotoPos(x, y);
  2138. X    }
  2139. X}
  2140. X
  2141. static void DeleteChar(n)
  2142. int n;
  2143. X{
  2144. X  register int i, y = curr->y, x = curr->x;
  2145. X
  2146. X  if (x == cols)
  2147. X    --x;
  2148. X  bcopy(curr->image[y], OldImage, cols);
  2149. X  bcopy(curr->attr[y], OldAttr, cols);
  2150. X  bcopy(curr->font[y], OldFont, cols);
  2151. X  if (n > cols - x)
  2152. X    n = cols - x;
  2153. X  bcopy(curr->image[y] + x + n, curr->image[y] + x, cols - x - n);
  2154. X  bcopy(curr->attr[y] + x + n, curr->attr[y] + x, cols - x - n);
  2155. X  bcopy(curr->font[y] + x + n, curr->font[y] + x, cols - x - n);
  2156. X  ClearInLine(0, y, cols - n, cols - 1);
  2157. X  if (!display)
  2158. X    return;
  2159. X  if (CDC && !(n == 1 && DC))
  2160. X    {
  2161. X      CPutStr(CDC, n);
  2162. X      if (lp_missing && y == screenbot)
  2163. X    {
  2164. X      FixLP(cols - 1 - n, y);
  2165. X          GotoPos(x, y);
  2166. X    }
  2167. X    }
  2168. X  else if (DC)
  2169. X    {
  2170. X      for (i = n; i; i--)
  2171. X    PutStr(DC);
  2172. X      if (lp_missing && y == screenbot)
  2173. X    {
  2174. X      FixLP(cols - 1 - n, y);
  2175. X          GotoPos(x, y);
  2176. X    }
  2177. X    }
  2178. X  else
  2179. X    {
  2180. X      RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
  2181. X      GotoPos(x, y);
  2182. X    }
  2183. X}
  2184. X
  2185. static void DeleteLine(n)
  2186. int n;
  2187. X{
  2188. X  register int old = curr->top;
  2189. X  
  2190. X  if (curr->y < curr->top || curr->y > curr->bot)
  2191. X    return;
  2192. X  if (n > curr->bot - curr->y + 1)
  2193. X    n = curr->bot - curr->y + 1;
  2194. X  curr->top = curr->y;
  2195. X  ScrollUpMap(n);
  2196. X  curr->top = old;
  2197. X  if (!display)
  2198. X    return;
  2199. X  ScrollRegion(curr->y, curr->bot, n);
  2200. X  GotoPos(curr->x, curr->y);
  2201. X}
  2202. X
  2203. static void InsertLine(n)
  2204. int n;
  2205. X{
  2206. X  register int old = curr->top;
  2207. X
  2208. X  if (curr->y < curr->top || curr->y > curr->bot)
  2209. X    return;
  2210. X  if (n > curr->bot - curr->y + 1)
  2211. X    n = curr->bot - curr->y + 1;
  2212. X  curr->top = curr->y;
  2213. X  ScrollDownMap(n);
  2214. X  curr->top = old;
  2215. X  if (!display)
  2216. X    return;
  2217. X  ScrollRegion(curr->y, curr->bot, -n);
  2218. X  GotoPos(curr->x, curr->y);
  2219. X}
  2220. X
  2221. void
  2222. ScrollRegion(ys, ye, n)
  2223. int ys, ye, n;
  2224. X{
  2225. X  int i;
  2226. X  int up;
  2227. X  int oldtop, oldbot;
  2228. X  int alok, dlok, aldlfaster;
  2229. X  int missy = 0;
  2230. X
  2231. X  if (n == 0)
  2232. X    return;
  2233. X  if (ys == 0 && ye == screenheight-1 && 
  2234. X      (n >= screenheight || -n >= screenheight))
  2235. X    {
  2236. X      PutStr(CL);
  2237. X      screeny = screenx = 0;
  2238. X      lp_missing = 0;
  2239. X      return;
  2240. X    }
  2241. X
  2242. X  if (lp_missing)
  2243. X    {
  2244. X      if (screenbot>ye || screenbot<ys)
  2245. X    missy = screenbot;
  2246. X      else
  2247. X    {
  2248. X      missy = screenbot - n;
  2249. X          if (missy>ye || missy<ys)
  2250. X        lp_missing = 0;
  2251. X    }
  2252. X    }
  2253. X
  2254. X  up = 1;
  2255. X  if (n < 0)
  2256. X    {
  2257. X      up = 0;
  2258. X      n = -n;
  2259. X    }
  2260. X  if (n >= ye-ys+1)
  2261. X    n = ye-ys+1;
  2262. X
  2263. X  oldtop = screentop;
  2264. X  oldbot = screenbot;
  2265. X  if (screenbot != ye)
  2266. X    ChangeScrollRegion(ys, ye);
  2267. X  alok = (AL || CAL || (ye == screenbot &&  up));
  2268. X  dlok = (DL || CDL || (ye == screenbot && !up));
  2269. X  if (screentop != ys && !(alok && dlok))
  2270. X    ChangeScrollRegion(ys, ye);
  2271. X
  2272. X  if (lp_missing && 
  2273. X      (oldbot != screenbot ||
  2274. X       oldbot == screenbot && up && screentop == ys && screenbot == ye))
  2275. X    {
  2276. X      /* Can't use FixLP */
  2277. X      GotoPos(screenwidth-1, oldbot);
  2278. X      SaveSetAttr(curr->attr[missy][screenwidth-1], curr->font[missy][screenwidth-1]);
  2279. X      PUTCHAR(curr->image[missy][screenwidth-1]);
  2280. X      RestoreAttr();
  2281. X      lp_missing = 0;
  2282. X      if (oldbot == screenbot)        /* have scrolled */
  2283. X    {
  2284. X      if (--n == 0)
  2285. X        {
  2286. X          ChangeScrollRegion(oldtop, oldbot);
  2287. X          return;
  2288. X        }
  2289. X    }
  2290. X    }
  2291. X
  2292. X  aldlfaster = (n > 1 && ye == screenbot && (up && CDL || !up && CAL));
  2293. X
  2294. X  if ((up || SR) && screentop == ys && screenbot == ye && !aldlfaster)
  2295. X    {
  2296. X      if (up)
  2297. X    {
  2298. X      GotoPos(0, ye);
  2299. X      while (n-- > 0)
  2300. X        PutStr(NL); /* was SF, I think NL is faster */
  2301. X    }
  2302. X      else
  2303. X    {
  2304. X      GotoPos(0, ys);
  2305. X      while (n-- > 0)
  2306. X        PutStr(SR);
  2307. X    }
  2308. X    }
  2309. X  else if (alok && dlok)
  2310. X    {
  2311. X      if (up || ye != screenbot)
  2312. X    {
  2313. X          GotoPos(0, up ? ys : ye+1-n);
  2314. X          if (CDL && !(n == 1 && DL))
  2315. X        CPutStr(CDL, n);
  2316. X      else
  2317. X        for(i=n; i--; )
  2318. X          PutStr(DL);
  2319. X    }
  2320. X      if (!up || ye != screenbot)
  2321. X    {
  2322. X          GotoPos(0, up ? ye+1-n : ys);
  2323. X          if (CAL && !(n == 1 && AL))
  2324. X        CPutStr(CAL, n);
  2325. X      else
  2326. X        for(i=n; i--; )
  2327. X          PutStr(AL);
  2328. X    }
  2329. X    }
  2330. X  else
  2331. X    {
  2332. X      Redisplay();
  2333. X      return;
  2334. X    }
  2335. X  if (lp_missing && missy != screenbot)
  2336. X    FixLP(screenwidth-1, missy);
  2337. X  ChangeScrollRegion(oldtop, oldbot);
  2338. X  if (lp_missing && missy != screenbot)
  2339. X    FixLP(screenwidth-1, missy);
  2340. X}
  2341. X
  2342. static void ScrollUpMap(n)
  2343. int n;
  2344. X{
  2345. X  char tmp[256 * sizeof(char *)];
  2346. X  register int ii, i, cnt1, cnt2;
  2347. X  register char **ppi, **ppa, **ppf;
  2348. X
  2349. X  i = curr->top + n;
  2350. X  cnt1 = n * sizeof(char *);
  2351. X  cnt2 = (curr->bot - i + 1) * sizeof(char *);
  2352. X  ppi = curr->image + i;
  2353. X  ppa = curr->attr + i;
  2354. X  ppf = curr->font + i;
  2355. X  for(ii = curr->top; ii < i; ii++)
  2356. X     AddLineToHist(curr, &curr->image[ii], &curr->attr[ii], &curr->font[ii]);
  2357. X  for (i = n; i; --i)
  2358. X    {
  2359. X      bclear(*--ppi, cols);
  2360. X      bzero(*--ppa, cols);
  2361. X      bzero(*--ppf, cols);
  2362. X    }
  2363. X  Scroll((char *) ppi, cnt1, cnt2, tmp);
  2364. X  Scroll((char *) ppa, cnt1, cnt2, tmp);
  2365. X  Scroll((char *) ppf, cnt1, cnt2, tmp);
  2366. X}
  2367. X
  2368. static void ScrollDownMap(n)
  2369. int n;
  2370. X{
  2371. X  char tmp[256 * sizeof(char *)];
  2372. X  register int i, cnt1, cnt2;
  2373. X  register char **ppi, **ppa, **ppf;
  2374. X
  2375. X  i = curr->top;
  2376. X  cnt1 = (curr->bot - i - n + 1) * sizeof(char *);
  2377. X  cnt2 = n * sizeof(char *);
  2378. X  Scroll((char *) (ppi = curr->image + i), cnt1, cnt2, tmp);
  2379. X  Scroll((char *) (ppa = curr->attr + i), cnt1, cnt2, tmp);
  2380. X  Scroll((char *) (ppf = curr->font + i), cnt1, cnt2, tmp);
  2381. X  for (i = n; i; --i)
  2382. X    {
  2383. X      bclear(*ppi++, cols);
  2384. X      bzero(*ppa++, cols);
  2385. X      bzero(*ppf++, cols);
  2386. X    }
  2387. X}
  2388. X
  2389. static void Scroll(cp, cnt1, cnt2, tmp)
  2390. char *cp, *tmp;
  2391. int cnt1, cnt2;
  2392. X{
  2393. X  if (!cnt1 || !cnt2)
  2394. X    return;
  2395. X  if (cnt1 <= cnt2)
  2396. X    {
  2397. X      bcopy(cp, tmp, cnt1);
  2398. X      bcopy(cp + cnt1, cp, cnt2);
  2399. X      bcopy(tmp, cp + cnt2, cnt1);
  2400. X    }
  2401. X  else
  2402. X    {
  2403. X      bcopy(cp + cnt1, tmp, cnt2);
  2404. X      bcopy(cp, cp + cnt2, cnt1);
  2405. X      bcopy(tmp, cp, cnt2);
  2406. X    }
  2407. X}
  2408. X
  2409. static void ForwardTab()
  2410. X{
  2411. X  register int x = curr->x;
  2412. X
  2413. X  if (x == cols)
  2414. X    {
  2415. X      LineFeed(2);
  2416. X      x = 0;
  2417. X    }
  2418. X  if (curr->tabs[x] && x < cols - 1)
  2419. X    x++;
  2420. X  while (x < cols - 1 && !curr->tabs[x])
  2421. X    x++;
  2422. X  GotoPos(x, curr->y);
  2423. X  curr->x = x;
  2424. X}
  2425. X
  2426. static void BackwardTab()
  2427. X{
  2428. X  register int x = curr->x;
  2429. X
  2430. X  if (curr->tabs[x] && x > 0)
  2431. X    x--;
  2432. X  while (x > 0 && !curr->tabs[x])
  2433. X    x--;
  2434. X  GotoPos(x, curr->y);
  2435. X  curr->x = x;
  2436. X}
  2437. X
  2438. static void ClearScreen()
  2439. X{
  2440. X  register int i;
  2441. X  register char **ppi = curr->image, **ppa = curr->attr, **ppf = curr->font;
  2442. X
  2443. X  for (i = 0; i < rows; ++i)
  2444. X    {
  2445. X      AddLineToHist(curr, ppi, ppa, ppf);
  2446. X      bclear(*ppi++, cols);
  2447. X      bzero(*ppa++, cols);
  2448. X      bzero(*ppf++, cols);
  2449. X    }
  2450. X  if (display)
  2451. X    {
  2452. X      PutStr(CL);
  2453. X      screenx = screeny = 0;
  2454. X      lp_missing = 0;
  2455. X    }
  2456. X}
  2457. X
  2458. static void ClearFromBOS()
  2459. X{
  2460. X  register int n, y = curr->y, x = curr->x;
  2461. X
  2462. X  for (n = 0; n < y; ++n)
  2463. X    ClearInLine(1, n, 0, cols - 1);
  2464. X  ClearInLine(1, y, 0, x);
  2465. X  GotoPos(x, y);
  2466. X  RestoreAttr();
  2467. X}
  2468. X
  2469. static void ClearToEOS()
  2470. X{
  2471. X  register int n, y = curr->y, x = curr->x;
  2472. X
  2473. X  if (!y && !x)
  2474. X    {
  2475. X      ClearScreen();
  2476. X      return;
  2477. X    }
  2478. X  if (display && CD)
  2479. X    {
  2480. X      PutStr(CD);
  2481. X      lp_missing = 0;
  2482. X    }
  2483. X  ClearInLine(!CD, y, x, cols - 1);
  2484. X  for (n = y + 1; n < rows; n++)
  2485. X    ClearInLine(!CD, n, 0, cols - 1);
  2486. X  GotoPos(x, y);
  2487. X  RestoreAttr();
  2488. X}
  2489. X
  2490. static void ClearLine()
  2491. X{
  2492. X  register int y = curr->y, x = curr->x;
  2493. X
  2494. X  ClearInLine(1, y, 0, cols - 1);
  2495. X  GotoPos(x, y);
  2496. X  RestoreAttr();
  2497. X}
  2498. X
  2499. static void ClearToEOL()
  2500. X{
  2501. X  register int y = curr->y, x = curr->x;
  2502. X
  2503. X  ClearInLine(1, y, x, cols - 1);
  2504. X  GotoPos(x, y);
  2505. X  RestoreAttr();
  2506. X}
  2507. X
  2508. static void ClearFromBOL()
  2509. X{
  2510. X  register int y = curr->y, x = curr->x;
  2511. X
  2512. X  ClearInLine(1, y, 0, x);
  2513. X  GotoPos(x, y);
  2514. X  RestoreAttr();
  2515. X}
  2516. X
  2517. static void ClearInLine(displ, y, x1, x2)
  2518. int displ, y, x1, x2;
  2519. X{
  2520. X  register int n;
  2521. X
  2522. X  if (x1 == cols)
  2523. X    x1--;
  2524. X  if (x2 == cols)
  2525. X    x2--;
  2526. X  if ((n = x2 - x1 + 1) != 0)
  2527. X    {
  2528. X      if (displ && display)
  2529. X    {
  2530. X      if (x2 == cols - 1 && CE)
  2531. X        {
  2532. X          GotoPos(x1, y);
  2533. X          PutStr(CE);
  2534. X          if (y == screenbot)
  2535. X        lp_missing = 0;
  2536. X        }
  2537. X      else
  2538. X        DisplayLine(curr->image[y], curr->attr[y], curr->font[y],
  2539. X            blank, null, null, y, x1, x2);
  2540. X    }
  2541. X      if (curr)
  2542. X    {
  2543. X          bclear(curr->image[y] + x1, n);
  2544. X          bzero(curr->attr[y] + x1, n);
  2545. X          bzero(curr->font[y] + x1, n);
  2546. X    }
  2547. X    }
  2548. X}
  2549. X
  2550. static void CursorRight(n)
  2551. register int n;
  2552. X{
  2553. X  register int x = curr->x;
  2554. X
  2555. X  if (x == cols)
  2556. X    {
  2557. X      LineFeed(2);
  2558. X      x = 0;
  2559. X    }
  2560. X  if ((curr->x += n) >= cols)
  2561. X    curr->x = cols - 1;
  2562. X  GotoPos(curr->x, curr->y);
  2563. X}
  2564. X
  2565. static void CursorUp(n)
  2566. register int n;
  2567. X{
  2568. X  if (curr->y < curr->top)        /* if above scrolling rgn, */
  2569. X    {
  2570. X      if ((curr->y -= n) < 0)        /* ignore it's limits      */
  2571. X         curr->y = 0;
  2572. X    }
  2573. X  else
  2574. X    if ((curr->y -= n) < curr->top)
  2575. X      curr->y = curr->top;
  2576. X  GotoPos(curr->x, curr->y);
  2577. X}
  2578. X
  2579. static void CursorDown(n)
  2580. register int n;
  2581. X{
  2582. X  if (curr->y > curr->bot)        /* if below scrolling rgn, */
  2583. X    {
  2584. X      if ((curr->y += n) > rows - 1)    /* ignore it's limits      */
  2585. X        curr->y = rows - 1;
  2586. X    }
  2587. X  else
  2588. X    if ((curr->y += n) > curr->bot)
  2589. X      curr->y = curr->bot;
  2590. X  GotoPos(curr->x, curr->y);
  2591. X}
  2592. X
  2593. static void CursorLeft(n)
  2594. register int n;
  2595. X{
  2596. X  if ((curr->x -= n) < 0)
  2597. X    curr->x = 0;
  2598. X  GotoPos(curr->x, curr->y);
  2599. X}
  2600. X
  2601. static void ASetMode(on)
  2602. int on;
  2603. X{
  2604. X  register int i;
  2605. X
  2606. X  for (i = 0; i < curr->NumArgs; ++i)
  2607. X    {
  2608. X      switch (curr->args[i])
  2609. X    {
  2610. X    case 4:
  2611. X      curr->insert = on;
  2612. X      InsertMode(on);
  2613. X      break;
  2614. X    }
  2615. X    }
  2616. X}
  2617. X
  2618. static void SelectRendition()
  2619. X{
  2620. X  register int i = 0, a = curr->LocalAttr;
  2621. X
  2622. X  do
  2623. X    {
  2624. X      switch (curr->args[i])
  2625. X    {
  2626. X    case 0:
  2627. X      a = 0;
  2628. X      break;
  2629. X    case 1:
  2630. X      a |= A_BD;
  2631. X      break;
  2632. X    case 2:
  2633. X      a |= A_DI;
  2634. X      break;
  2635. X    case 3:
  2636. X      a |= A_SO;
  2637. X      break;
  2638. X    case 4:
  2639. X      a |= A_US;
  2640. X      break;
  2641. X    case 5:
  2642. X      a |= A_BL;
  2643. X      break;
  2644. X    case 7:
  2645. X      a |= A_RV;
  2646. X      break;
  2647. X    case 22:
  2648. X      a &= ~(A_BD | A_SO | A_DI);
  2649. X      break;
  2650. X    case 23:
  2651. X      a &= ~A_SO;
  2652. X      break;
  2653. X    case 24:
  2654. X      a &= ~A_US;
  2655. X      break;
  2656. X    case 25:
  2657. X      a &= ~A_BL;
  2658. X      break;
  2659. X    case 27:
  2660. X      a &= ~A_RV;
  2661. X      break;
  2662. X    }
  2663. X    } while (++i < curr->NumArgs);
  2664. X  NewRendition(curr->LocalAttr = a);
  2665. X}
  2666. X
  2667. void
  2668. NewRendition(new)
  2669. register int new;
  2670. X{
  2671. X  register int i, old = GlobalAttr;
  2672. X
  2673. X  if (!display || old == new)
  2674. X    return;
  2675. X  GlobalAttr = new;
  2676. X  for (i = 1; i <= A_MAX; i <<= 1)
  2677. X    {
  2678. X      if ((old & i) && !(new & i))
  2679. X    {
  2680. X      PutStr(UE);
  2681. X      PutStr(SE);
  2682. X      PutStr(ME);
  2683. X      if (new & A_DI)
  2684. X        PutStr(attrtab[ATTR_DI]);
  2685. X      if (new & A_US)
  2686. X        PutStr(attrtab[ATTR_US]);
  2687. X      if (new & A_BD)
  2688. X        PutStr(attrtab[ATTR_BD]);
  2689. X      if (new & A_RV)
  2690. X        PutStr(attrtab[ATTR_RV]);
  2691. X      if (new & A_SO)
  2692. X        PutStr(attrtab[ATTR_SO]);
  2693. X      if (new & A_BL)
  2694. X        PutStr(attrtab[ATTR_BL]);
  2695. X      return;
  2696. X    }
  2697. X    }
  2698. X  if ((new & A_DI) && !(old & A_DI))
  2699. X    PutStr(attrtab[ATTR_DI]);
  2700. X  if ((new & A_US) && !(old & A_US))
  2701. X    PutStr(attrtab[ATTR_US]);
  2702. X  if ((new & A_BD) && !(old & A_BD))
  2703. X    PutStr(attrtab[ATTR_BD]);
  2704. X  if ((new & A_RV) && !(old & A_RV))
  2705. X    PutStr(attrtab[ATTR_RV]);
  2706. X  if ((new & A_SO) && !(old & A_SO))
  2707. X    PutStr(attrtab[ATTR_SO]);
  2708. X  if ((new & A_BL) && !(old & A_BL))
  2709. X    PutStr(attrtab[ATTR_BL]);
  2710. X}
  2711. X
  2712. void
  2713. SaveSetAttr(newattr, newcharset)
  2714. int newattr, newcharset;
  2715. X{
  2716. X  NewRendition(newattr);
  2717. X  NewCharset(newcharset);
  2718. X}
  2719. X
  2720. void
  2721. RestoreAttr()
  2722. X{
  2723. X  NewRendition(curr->LocalAttr);
  2724. X  NewCharset(curr->charsets[curr->LocalCharset]);
  2725. X}
  2726. X
  2727. static void FillWithEs()
  2728. X{
  2729. X  register int i;
  2730. X  register char *p, *ep;
  2731. X
  2732. X  curr->y = curr->x = 0;
  2733. X  for (i = 0; i < rows; ++i)
  2734. X    {
  2735. X      bzero(curr->attr[i], cols);
  2736. X      bzero(curr->font[i], cols);
  2737. X      p = curr->image[i];
  2738. X      ep = p + cols;
  2739. X      while (p < ep)
  2740. X    *p++ = 'E';
  2741. X    }
  2742. X  if (display)
  2743. X    Redisplay();
  2744. X}
  2745. X
  2746. void Redisplay()
  2747. X{
  2748. X  register int i;
  2749. X
  2750. X  PutStr(CL);
  2751. X  screenx = screeny = 0;
  2752. X  lp_missing = 0;
  2753. X  for (i = 0; i < rows; ++i)
  2754. X    {
  2755. X      if (in_ovl)
  2756. X    (*ovl_RedisplayLine)(i, 0, cols - 1, 1);
  2757. X      else
  2758. X        DisplayLine(blank, null, null, curr->image[i], curr->attr[i],
  2759. X            curr->font[i], i, 0, cols - 1);
  2760. X    }
  2761. X  if (!in_ovl)
  2762. X    {
  2763. X      GotoPos(curr->x, curr->y);
  2764. X      NewRendition(curr->LocalAttr);
  2765. X      NewCharset(curr->charsets[curr->LocalCharset]);
  2766. X    }
  2767. X}
  2768. X
  2769. void
  2770. DisplayLine(os, oa, of, s, as, fs, y, from, to)
  2771. int from, to, y;
  2772. register char *os, *oa, *of, *s, *as, *fs;
  2773. X{
  2774. X  register int x;
  2775. X  int last2flag = 0, delete_lp = 0;
  2776. X
  2777. X  if (!LP && y == screenbot && to == cols - 1)
  2778. X    if (lp_missing
  2779. X    || s[to] != os[to] || as[to] != oa[to] || of[to] != fs[to])
  2780. X      {
  2781. X    if ((IC || IM) && (from < to || !in_ovl))
  2782. X      {
  2783. X        if ((to -= 2) < from - 1)
  2784. X          from--;
  2785. X        last2flag = 1;
  2786. X        lp_missing = 0;
  2787. X      }
  2788. X    else
  2789. X      {
  2790. X        to--;
  2791. X        delete_lp = (CE || DC || CDC);
  2792. X        lp_missing = (s[to] != ' ' || as[to] || fs[to]);
  2793. X      }
  2794. X      }
  2795. X    else
  2796. X      to--;
  2797. X  for (x = from; x <= to; ++x)
  2798. X    {
  2799. X      if (s[x] == os[x] && as[x] == oa[x] && of[x] == fs[x])
  2800. X    continue;
  2801. X      GotoPos(x, y);
  2802. X      NewRendition(as[x]);
  2803. X      NewCharset(fs[x]);
  2804. X      PUTCHAR(s[x]);
  2805. X    }
  2806. X  if (last2flag)
  2807. X    {
  2808. X      GotoPos(x, y);
  2809. X      NewRendition(as[x + 1]);
  2810. X      NewCharset(fs[x + 1]);
  2811. X      PUTCHAR(s[x + 1]);
  2812. X      GotoPos(x, y);
  2813. X      NewRendition(as[x]);
  2814. X      NewCharset(fs[x]);
  2815. X      INSERTCHAR(s[x]);
  2816. X    }
  2817. X  else if (delete_lp)
  2818. X    {
  2819. X      if (DC)
  2820. X    PutStr(DC);
  2821. X      else if (CDC)
  2822. X    CPutStr(CDC, 1);
  2823. X      else if (CE)
  2824. X    PutStr(CE);
  2825. X    }
  2826. X}
  2827. X
  2828. void
  2829. RefreshLine(y, from, to)
  2830. int y, from, to;
  2831. X{
  2832. X  char *oi = null;
  2833. X
  2834. X  if (CE && to == screenwidth-1)
  2835. X    {
  2836. X      GotoPos(from, y);
  2837. X      PutStr(CE);
  2838. X      oi = blank;
  2839. X    }
  2840. X  if (in_ovl)
  2841. X    (*ovl_RedisplayLine)(y, from, to, (oi == blank));
  2842. X  else
  2843. X    DisplayLine(oi, null, null, curr->image[y], curr->attr[y],
  2844. X                curr->font[y], y, from, to);
  2845. X}
  2846. X
  2847. static void RedisplayLine(os, oa, of, y, from, to)
  2848. int from, to, y;
  2849. char *os, *oa, *of;
  2850. X{
  2851. X  DisplayLine(os, oa, of, curr->image[y], curr->attr[y],
  2852. X          curr->font[y], y, from, to);
  2853. X  NewRendition(curr->LocalAttr);
  2854. X  NewCharset(curr->charsets[curr->LocalCharset]);
  2855. X}
  2856. X
  2857. void
  2858. XFixLP(x2, y2)
  2859. register int x2, y2;
  2860. X{
  2861. X  register struct win *p = curr;
  2862. X
  2863. X  GotoPos(x2, y2);
  2864. X  SaveSetAttr(p->attr[y2][x2], p->font[y2][x2]);
  2865. X  PUTCHAR(p->image[y2][x2]);
  2866. X  RestoreAttr();
  2867. X  lp_missing = 0;
  2868. X}
  2869. X
  2870. void
  2871. CheckLP(n_ch)
  2872. char n_ch;
  2873. X{
  2874. X  register int y = screenbot, x = cols - 1;
  2875. X  register char n_at, n_fo, o_ch, o_at, o_fo;
  2876. X
  2877. X  o_ch = curr->image[y][x];
  2878. X  o_at = curr->attr[y][x];
  2879. X  o_fo = curr->font[y][x];
  2880. X
  2881. X  n_at = curr->LocalAttr;
  2882. X  n_fo = curr->charsets[curr->LocalCharset];
  2883. X
  2884. X  lp_missing = 0;
  2885. X  if (n_ch == o_ch && n_at == o_at && n_fo == o_fo)
  2886. X    {
  2887. X      return;
  2888. X    }
  2889. X  if (n_ch != ' ' || n_at || n_fo)
  2890. X    lp_missing = 1;
  2891. X  if (o_ch != ' ' || o_at || o_fo)
  2892. X    {
  2893. X      if (DC)
  2894. X    PutStr(DC);
  2895. X      else if (CDC)
  2896. X    CPutStr(CDC, 1);
  2897. X      else if (CE)
  2898. X    PutStr(CE);
  2899. X      else
  2900. X    lp_missing = 1;
  2901. X    }
  2902. X}
  2903. X
  2904. static void FindAKA()
  2905. X{
  2906. X  register char *cp, *line, ch;
  2907. X  register struct win *wp = curr;
  2908. X  register int len = strlen(wp->cmd);
  2909. X  int y;
  2910. X
  2911. X  y = (wp->autoaka > 0 && wp->autoaka <= wp->height) ? wp->autoaka - 1 : wp->y;
  2912. X  cols = wp->width;
  2913. X try_line:
  2914. X  cp = line = wp->image[y];
  2915. X  if (wp->autoaka > 0 && (ch = *wp->cmd) != '\0')
  2916. X    {
  2917. X      for (;;)
  2918. X    {
  2919. X      if ((cp = index(cp, ch)) != NULL
  2920. X          && !strncmp(cp, wp->cmd, len))
  2921. X        break;
  2922. X      if (!cp || ++cp - line >= cols - len)
  2923. X        {
  2924. X          if (++y == wp->autoaka && y < rows)
  2925. X        goto try_line;
  2926. X          return;
  2927. X        }
  2928. X    }
  2929. X      cp += len;
  2930. X    }
  2931. X  for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
  2932. X    ;
  2933. X  if (len)
  2934. X    {
  2935. X      if (wp->autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
  2936. X    wp->autoaka = -1;
  2937. X      else
  2938. X    wp->autoaka = 0;
  2939. X      line = wp->cmd + wp->akapos;
  2940. X      while (len && *cp != ' ')
  2941. X    {
  2942. X      if ((*line++ = *cp++) == '/')
  2943. X        line = wp->cmd + wp->akapos;
  2944. X      len--;
  2945. X    }
  2946. X      *line = '\0';
  2947. X    }
  2948. X  else
  2949. X    wp->autoaka = 0;
  2950. X}
  2951. X
  2952. X
  2953. X/* We dont use HS status line with Input.
  2954. X * If we would use it, then we should check e_tgetflag("es") if
  2955. X * we are allowed to use esc sequences there.
  2956. X * For now, we hope that Goto(,,STATLINE,0) brings us in the bottom
  2957. X * line. jw.
  2958. X */
  2959. X
  2960. static char inpbuf[101];
  2961. static int inplen;
  2962. static int inpmaxlen;
  2963. static char *inpstring;
  2964. static int inpstringlen;
  2965. static void (*inpfinfunc)();
  2966. X
  2967. void
  2968. Input(istr, len, finfunc)
  2969. char *istr;
  2970. int len;
  2971. void (*finfunc)();
  2972. X{
  2973. X  int maxlen;
  2974. X
  2975. X  inpstring = istr;
  2976. X  inpstringlen = strlen(istr);
  2977. X  if (len > 100)
  2978. X    len = 100;
  2979. X  maxlen = screenwidth - inpstringlen;
  2980. X  if (!LP && STATLINE == screenbot)
  2981. X    maxlen--;
  2982. X  if (len > maxlen)
  2983. X    len = maxlen;
  2984. X  if (len < 2)
  2985. X    {
  2986. X      Msg(0, "Width too small");
  2987. X      return;
  2988. X    }
  2989. X  inpmaxlen = len;
  2990. X  inpfinfunc = finfunc;
  2991. X  InitOverlayPage(process_inp_input, inpRedisplayLine, (int (*)())0, 1);
  2992. X  inplen = 0;
  2993. X  GotoPos(0, STATLINE);
  2994. X  if (CE)
  2995. X    PutStr(CE);
  2996. X  else
  2997. X    {
  2998. X      DisplayLine(curr->image[screeny], curr->attr[screeny],
  2999. X          curr->font[screeny],
  3000. X          blank, null, null, screeny, 0, cols - 1);
  3001. X    }
  3002. X  inpRedisplayLine(STATLINE, 0, inpstringlen - 1, 0);
  3003. X  GotoPos(inpstringlen, STATLINE);
  3004. X}
  3005. X
  3006. static void
  3007. process_inp_input(ppbuf, plen)
  3008. char **ppbuf;
  3009. int *plen;
  3010. X{
  3011. X  int len, x;
  3012. X  char *pbuf;
  3013. X  char ch;
  3014. X
  3015. X  if (ppbuf == 0)
  3016. X    {
  3017. X      AbortInp();
  3018. X      return;
  3019. X    }
  3020. X  x = inpstringlen+inplen;
  3021. X  len = *plen;
  3022. X  pbuf = *ppbuf;
  3023. X  while (len)
  3024. X    {
  3025. X      ch = *pbuf++;
  3026. X      len--;
  3027. X      if (ch >= ' ' && ch <= '~' && inplen < inpmaxlen)
  3028. X    {
  3029. X      inpbuf[inplen++] = ch;
  3030. X        GotoPos(x, STATLINE);
  3031. X      SaveSetAttr(A_SO, ASCII);
  3032. X      PUTCHAR(ch);
  3033. X      x++;
  3034. X    }
  3035. X      else if ((ch == '\b' || ch == 0177) && inplen > 0)
  3036. X    {
  3037. X      inplen--;
  3038. X      x--;
  3039. X        GotoPos(x, STATLINE);
  3040. X      SaveSetAttr(0, ASCII);
  3041. X      PUTCHAR(' ');
  3042. X        GotoPos(x, STATLINE);
  3043. X    }
  3044. X      else if (ch == '\004' || ch == '\003' || ch == '\000' || ch == '\n' || ch == '\r')
  3045. X    {
  3046. X          if (ch != '\n' && ch != '\r')
  3047. X        inplen = 0;
  3048. X      inpbuf[inplen] = 0;
  3049. X          AbortInp(); /* redisplays... */
  3050. X          (*inpfinfunc)(inpbuf, inplen);
  3051. X      break;
  3052. X    }
  3053. X    }
  3054. X  *ppbuf = pbuf;
  3055. X  *plen = len;
  3056. X}
  3057. X
  3058. static void
  3059. AbortInp()
  3060. X{
  3061. X  in_ovl = 0;    /* So we can use RefreshLine() */
  3062. X  RefreshLine(STATLINE, 0, screenwidth-1);
  3063. X  ExitOverlayPage();
  3064. X}
  3065. X
  3066. static void
  3067. inpRedisplayLine(y, xs, xe, isblank)
  3068. int y, xs, xe, isblank;
  3069. X{
  3070. X  int q, r, s, l, v;
  3071. X
  3072. X  if (y != STATLINE)
  3073. X    return;
  3074. X  inpbuf[inplen] = 0;
  3075. X  GotoPos(xs,y);
  3076. X  q = xs;
  3077. X  v = xe - xs + 1;
  3078. X  s = 0;
  3079. X  r = inpstringlen;
  3080. X  if (v > 0 && q < r)
  3081. X    {
  3082. X      SaveSetAttr(A_SO, ASCII);
  3083. X      l = v;
  3084. X      if (l > r-q)
  3085. X    l = r-q;
  3086. X      printf("%-*.*s", l, l, inpstring + q - s);
  3087. X      q += l;
  3088. X      v -= l;
  3089. X    }
  3090. X  s = r;
  3091. X  r += inplen;
  3092. X  if (v > 0 && q < r)
  3093. X    {
  3094. X      SaveSetAttr(A_SO, ASCII);
  3095. X      l = v;
  3096. X      if (l > r-q)
  3097. X    l = r-q;
  3098. X      printf("%-*.*s", l, l, inpbuf + q - s);
  3099. X      q += l;
  3100. X      v -= l;
  3101. X    }
  3102. X  s = r;
  3103. X  r = screenwidth;
  3104. X  if (!isblank && v > 0 && q < r)
  3105. X    {
  3106. X      SaveSetAttr(0, ASCII);
  3107. X      l = v;
  3108. X      if (l > r-q)
  3109. X    l = r-q;
  3110. X      printf("%-*.*s", l, l, "");
  3111. X      q += l;
  3112. X    }
  3113. X  SetLastPos(q, y);
  3114. X}
  3115. X
  3116. static void
  3117. AKAfin(buf, len)
  3118. char *buf;
  3119. int len;
  3120. X{
  3121. X  if (len)
  3122. X    {
  3123. X      strcpy(curr->cmd + curr->akapos, buf);
  3124. X    }
  3125. X}
  3126. X
  3127. void
  3128. InputAKA()
  3129. X{
  3130. X  void Input(), AKAfin();
  3131. X
  3132. X  Input("Set window's a.k.a. to: ", 20, AKAfin);
  3133. X}
  3134. X
  3135. static void
  3136. Colonfin(buf, len)
  3137. char *buf;
  3138. int len;
  3139. X{
  3140. X  if (len)
  3141. X    RcLine(buf);
  3142. X}
  3143. X
  3144. void
  3145. InputColon()
  3146. X{
  3147. X  void Input(), Colonfin();
  3148. X
  3149. X  Input(":", 100, Colonfin);
  3150. X}
  3151. X
  3152. void
  3153. MakeBlankLine(p, n)
  3154. register char *p;
  3155. register int n;
  3156. X{
  3157. X  while (n--)
  3158. X    *p++ = ' ';
  3159. X}
  3160. X
  3161. void
  3162. MakeStatus(msg)
  3163. char *msg;
  3164. X{
  3165. X  register char *s, *t;
  3166. X  register int max, ti;
  3167. X
  3168. X  SetCurr(fore);
  3169. X  display = 1;
  3170. X  if (!(max = HS))
  3171. X    {
  3172. X      max = !LP ? cols - 1 : cols;
  3173. X    }
  3174. X  if (status)
  3175. X    {
  3176. X      if (!BellDisplayed)
  3177. X    {
  3178. X      ti = time((time_t *) 0) - TimeDisplayed;
  3179. X      if (ti < MsgMinWait)
  3180. X        sleep(MsgMinWait - ti);
  3181. X    }
  3182. X      RemoveStatus();
  3183. X    }
  3184. X  for (s = t = msg; *s && t - msg < max; ++s)
  3185. X    if (*s == BELL)
  3186. X      PutStr(BL);
  3187. X    else if (*s >= ' ' && *s <= '~')
  3188. X      *t++ = *s;
  3189. X  *t = '\0';
  3190. X  if (t > msg)
  3191. X    {
  3192. X      strncpy(LastMsg, msg, maxwidth);
  3193. X      status = 1;
  3194. X      status_lastx = screenx;
  3195. X      status_lasty = screeny;
  3196. X      StatLen = t - msg;
  3197. X      if (!HS)
  3198. X    {
  3199. X      GotoPos(0, STATLINE);
  3200. X          SaveSetAttr(A_SO, ASCII);
  3201. X      InsertMode(0);
  3202. X      printf("%s", msg);
  3203. X          screenx = -1;
  3204. X    }
  3205. X      else
  3206. X    {
  3207. X      debug("HS:");
  3208. X          SaveSetAttr(A_SO, ASCII);
  3209. X      InsertMode(0);
  3210. X      CPutStr(TS, 0);
  3211. X      printf("%s", msg);
  3212. X      PutStr(FS);
  3213. X    }
  3214. X      (void) fflush(stdout);
  3215. X      (void) time(&TimeDisplayed);
  3216. X    }
  3217. X}
  3218. X
  3219. void
  3220. RemoveStatus()
  3221. X{
  3222. X  if (!status)
  3223. X    return;
  3224. X  status = 0;
  3225. X  BellDisplayed = 0;
  3226. X  SetCurr(fore);
  3227. X  display = 1;
  3228. X  if (!HS)
  3229. X    {
  3230. X      GotoPos(0, STATLINE);
  3231. X      if (in_ovl)
  3232. X    (*ovl_RedisplayLine)(STATLINE, 0, StatLen - 1, 0);
  3233. X      else
  3234. X    RedisplayLine(null, null, null, STATLINE, 0, StatLen - 1);
  3235. X      GotoPos(status_lastx, status_lasty);
  3236. X    }
  3237. X  else
  3238. X    {
  3239. X      PutStr(DS);
  3240. X    }
  3241. X}
  3242. X
  3243. void
  3244. ClearDisplay()
  3245. X{
  3246. X  PutStr(CL);
  3247. X  screeny = screenx = 0;
  3248. X  fflush(stdout);
  3249. X}
  3250. X
  3251. static void SetCurr(wp)
  3252. struct win *wp;
  3253. X{
  3254. X  curr = wp;
  3255. X  cols = curr->width;
  3256. X  rows = curr->height;
  3257. X  display = curr->active;
  3258. X}
  3259. X
  3260. void
  3261. InitOverlayPage(pro, red, rewrite, blockfore)
  3262. void (*pro)();
  3263. void (*red)();
  3264. int (*rewrite)();
  3265. int blockfore;
  3266. X{
  3267. X  RemoveStatus();
  3268. X  SetOvlCurr();
  3269. X  ChangeScrollRegion(0, screenheight - 1);
  3270. X  ovl_process = pro;
  3271. X  ovl_RedisplayLine = red;
  3272. X  ovl_Rewrite = rewrite;
  3273. X  ovl_blockfore = blockfore;
  3274. X  curr->active = 0;
  3275. X  in_ovl = 1;
  3276. X}
  3277. X
  3278. void
  3279. XExitOverlayPage()
  3280. X{
  3281. X  GotoPos(curr->x, curr->y);
  3282. X  RestoreAttr();
  3283. X  ChangeScrollRegion(curr->top, curr->bot);
  3284. X  curr->active = 1;
  3285. X  in_ovl = 0;
  3286. X}
  3287. X
  3288. void
  3289. SetOvlCurr()
  3290. X{
  3291. X  SetCurr(fore);
  3292. X  SaveSetAttr(0, ASCII);
  3293. X  InsertMode(0);
  3294. X  display = 1;
  3295. X}
  3296. X
  3297. void
  3298. SetLastPos(x,y)
  3299. int x,y;
  3300. X{
  3301. X  screenx = x;
  3302. X  screeny = y;
  3303. X}
  3304. X
  3305. void
  3306. WSresize(width, height)
  3307. int width, height;
  3308. X{
  3309. X  debug2("(display=%d:WSresize says:'%s'\n", display, tgoto(WS, width, height));
  3310. X  PutStr(tgoto(WS, width, height));
  3311. X}
  3312. X
  3313. void
  3314. ChangeScrollRegion(top, bot)
  3315. int top, bot;
  3316. X{
  3317. X  if (display == 0)
  3318. X    return;
  3319. X  if (CS == 0)
  3320. X    {
  3321. X      screentop = 0;
  3322. X      screenbot = screenheight - 1;
  3323. X      return;
  3324. X    }
  3325. X  if (top == screentop && bot == screenbot)
  3326. X    return;
  3327. X  debug2("ChangeScrollRegion: (%d - %d)\n", top, bot);
  3328. X  PutStr(tgoto(CS, bot, top));
  3329. X  screentop = top;
  3330. X  screenbot = bot;
  3331. X  screeny = screenx = -1;        /* Just in case... */
  3332. X}
  3333. X
  3334. X
  3335. void AddLineToHist(wp, pi, pa, pf)
  3336. struct win *wp;
  3337. char **pi, **pa, **pf;
  3338. X{
  3339. X  register char *q;
  3340. X
  3341. X  if (wp->histheight == 0)
  3342. X    return;
  3343. X  q = *pi; *pi = wp->ihist[wp->histidx]; wp->ihist[wp->histidx] = q;
  3344. X  q = *pa; *pa = wp->ahist[wp->histidx]; wp->ahist[wp->histidx] = q;
  3345. X  q = *pf; *pf = wp->fhist[wp->histidx]; wp->fhist[wp->histidx] = q;
  3346. X  if (++wp->histidx >= wp->histheight)
  3347. X    wp->histidx = 0;
  3348. X}
  3349. X
  3350. X
  3351. X/*
  3352. X *
  3353. X *  Termcap routines that use our extra_incap
  3354. X *
  3355. X */
  3356. X
  3357. X/* findcap:
  3358. X *   cap = capability we are looking for
  3359. X *   tepp = pointer to bufferpointer
  3360. X *   n = size of buffer (0 = infinity)
  3361. X */
  3362. X
  3363. char *
  3364. findcap(cap, tepp, n)
  3365. char *cap;
  3366. char **tepp;
  3367. int n;
  3368. X{
  3369. X  char *tep;
  3370. X  char c, *p, *cp;
  3371. X  int mode;    /* mode: 0=LIT  1=^  2=\x  3,4,5=\nnn */
  3372. X  int num = 0, capl;
  3373. X
  3374. X  if (!extra_incap)
  3375. X    return (0);
  3376. X  tep = *tepp;
  3377. X  capl = strlen(cap);
  3378. X  cp = 0;
  3379. X  mode = 0;
  3380. X  for (p = extra_incap; *p; )
  3381. X    {
  3382. X      if (strncmp(p, cap, capl) == 0)
  3383. X    {
  3384. X      p+=capl;
  3385. X      c = *p;
  3386. X      if (c && c != ':' && c != '@')
  3387. X        p++;
  3388. X      if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#')
  3389. X        cp = tep;
  3390. X    }
  3391. X      while (c = *p)
  3392. X    {
  3393. X      p++;
  3394. X      if (mode == 0)
  3395. X        {
  3396. X          if (c == ':')
  3397. X            break;
  3398. X          if (c == '^')
  3399. X        mode = 1;
  3400. X          if (c == '\\')
  3401. X        mode = 2;
  3402. X        }
  3403. X      else if (mode == 1)
  3404. X        {
  3405. X          c = c & 0x1f;
  3406. X          mode = 0;
  3407. X        }
  3408. X      else if (mode == 2)
  3409. X        {
  3410. X          switch(c)
  3411. X        {
  3412. X        case '0':
  3413. X        case '1':
  3414. X        case '2':
  3415. X        case '3':
  3416. X        case '4':
  3417. X        case '5':
  3418. X        case '6':
  3419. X        case '7':
  3420. X        case '8':
  3421. X        case '9':
  3422. X          mode = 3;
  3423. X          num = 0;
  3424. X          break;
  3425. X        case 'E':
  3426. X          c = 27;
  3427. X          break;
  3428. X        case 'n':
  3429. X          c = '\n';
  3430. X          break;
  3431. X        case 'r':
  3432. X          c = '\r';
  3433. X          break;
  3434. X        case 't':
  3435. X          c = '\t';
  3436. X          break;
  3437. X        case 'b':
  3438. X          c = '\b';
  3439. X          break;
  3440. X        case 'f':
  3441. X          c = '\f';
  3442. X          break;
  3443. X        }
  3444. X          if (mode == 2)
  3445. X        mode = 0;
  3446. X        }
  3447. X      if (mode > 2)
  3448. X        {
  3449. X          num = num * 8 + (c - '0');
  3450. X          if (mode++ == 5 || (*p < '0' || *p > '9'))
  3451. X        {
  3452. X          c = num;
  3453. X          mode = 0;
  3454. X        }
  3455. X        }
  3456. X      if (mode)
  3457. X        continue;
  3458. X
  3459. X      if (cp && n != 1)
  3460. X        {
  3461. X          *cp++ = c;
  3462. X          n--;
  3463. X        }
  3464. X    }
  3465. X      if (cp)
  3466. X    {
  3467. X      *cp++ = 0;
  3468. X      *tepp = cp;
  3469. X      debug2("'%s' found in extra_incap -> %s\n", cap, tep);
  3470. X      return(tep);
  3471. X    }
  3472. X    }
  3473. X  return(0);
  3474. X}
  3475. X
  3476. static char *
  3477. e_tgetstr(cap, tepp)
  3478. char *cap;
  3479. char **tepp;
  3480. X{
  3481. X  char *tep;
  3482. X  if (tep = findcap(cap, tepp, 0))
  3483. X    return((*tep == '@') ? 0 : tep);
  3484. X  return (tgetstr(cap, tepp));
  3485. X}
  3486. X
  3487. static int
  3488. e_tgetflag(cap)
  3489. char *cap;
  3490. X{
  3491. X  char buf[2], *bufp;
  3492. X  char *tep;
  3493. X  bufp = buf;
  3494. X  if (tep = findcap(cap, &bufp, 2))
  3495. X    return((*tep == '@') ? 0 : 1);
  3496. X  return (tgetflag(cap));
  3497. X}
  3498. X
  3499. static int
  3500. e_tgetnum(cap)
  3501. char *cap;
  3502. X{
  3503. X  char buf[20], *bufp;
  3504. X  char *tep, c;
  3505. X  int res, base = 10;
  3506. X
  3507. X  bufp = buf;
  3508. X  if (tep = findcap(cap, &bufp, 20))
  3509. X    {
  3510. X      c = *tep;
  3511. X      if (c == '@')
  3512. X    return(-1);
  3513. X      if (c == '0')
  3514. X    base = 8;
  3515. X      res = 0;
  3516. X      while ((c = *tep++) >= '0' && c <= '9')
  3517. X    res = res * base + (c - '0');
  3518. X      return(res);
  3519. X    }
  3520. X  return (tgetnum(cap));
  3521. X}
  3522. END_OF_FILE
  3523. if test 68134 -ne `wc -c <'ansi.c'`; then
  3524.     echo shar: \"'ansi.c'\" unpacked with wrong size!
  3525. fi
  3526. # end of 'ansi.c'
  3527. fi
  3528. echo shar: End of archive 7 \(of 8\).
  3529. cp /dev/null ark7isdone
  3530. MISSING=""
  3531. for I in 1 2 3 4 5 6 7 8 ; do
  3532.     if test ! -f ark${I}isdone ; then
  3533.     MISSING="${MISSING} ${I}"
  3534.     fi
  3535. done
  3536. if test "${MISSING}" = "" ; then
  3537.     echo You have unpacked all 8 archives.
  3538.     rm -f ark[1-9]isdone
  3539. else
  3540.     echo You still need to unpack the following archives:
  3541.     echo "        " ${MISSING}
  3542. fi
  3543. ##  End of shell archive.
  3544. exit 0
  3545.